mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-15 10:09:59 +00:00
trivial: reformat all python code with black
This commit is contained in:
parent
b5555003bb
commit
6d1afc3e87
@ -7,72 +7,72 @@ import shutil
|
||||
|
||||
def prepare(target):
|
||||
# clone the flatpak json
|
||||
cmd = ['git', 'submodule', 'update', '--remote', 'contrib/flatpak']
|
||||
cmd = ["git", "submodule", "update", "--remote", "contrib/flatpak"]
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
# clone the submodules for that
|
||||
cmd = ['git', 'submodule', 'update', '--init', '--remote', 'shared-modules/']
|
||||
subprocess.run(cmd, cwd='contrib/flatpak', check=True)
|
||||
cmd = ["git", "submodule", "update", "--init", "--remote", "shared-modules/"]
|
||||
subprocess.run(cmd, cwd="contrib/flatpak", check=True)
|
||||
|
||||
# parse json
|
||||
if os.path.isdir('build'):
|
||||
shutil.rmtree('build')
|
||||
if os.path.isdir("build"):
|
||||
shutil.rmtree("build")
|
||||
data = {}
|
||||
with open('contrib/flatpak/org.freedesktop.fwupd.json', 'r') as rfd:
|
||||
with open("contrib/flatpak/org.freedesktop.fwupd.json", "r") as rfd:
|
||||
data = json.load(rfd, strict=False)
|
||||
platform = 'runtime/%s/x86_64/%s' % (data['runtime'], data['runtime-version'])
|
||||
sdk = 'runtime/%s/x86_64/%s' % (data['sdk'], data['runtime-version'])
|
||||
num_modules = len(data['modules'])
|
||||
platform = "runtime/%s/x86_64/%s" % (data["runtime"], data["runtime-version"])
|
||||
sdk = "runtime/%s/x86_64/%s" % (data["sdk"], data["runtime-version"])
|
||||
num_modules = len(data["modules"])
|
||||
|
||||
# update to build from master
|
||||
data["branch"] = "master"
|
||||
for index in range(0, num_modules):
|
||||
module = data['modules'][index]
|
||||
if type(module) != dict or not 'name' in module:
|
||||
module = data["modules"][index]
|
||||
if type(module) != dict or not "name" in module:
|
||||
continue
|
||||
name = module['name']
|
||||
if not 'fwupd' in name:
|
||||
name = module["name"]
|
||||
if not "fwupd" in name:
|
||||
continue
|
||||
data['modules'][index]['sources'][0].pop('url')
|
||||
data['modules'][index]['sources'][0].pop('sha256')
|
||||
data['modules'][index]['sources'][0]['type'] = 'dir'
|
||||
data['modules'][index]['sources'][0]['skip'] = [".git"]
|
||||
data['modules'][index]['sources'][0]['path'] = ".."
|
||||
data["modules"][index]["sources"][0].pop("url")
|
||||
data["modules"][index]["sources"][0].pop("sha256")
|
||||
data["modules"][index]["sources"][0]["type"] = "dir"
|
||||
data["modules"][index]["sources"][0]["skip"] = [".git"]
|
||||
data["modules"][index]["sources"][0]["path"] = ".."
|
||||
|
||||
# write json
|
||||
os.mkdir('build')
|
||||
with open(target, 'w') as wfd:
|
||||
os.mkdir("build")
|
||||
with open(target, "w") as wfd:
|
||||
json.dump(data, wfd, indent=4)
|
||||
os.symlink('../contrib/flatpak/shared-modules', 'build/shared-modules')
|
||||
os.symlink("../contrib/flatpak/shared-modules", "build/shared-modules")
|
||||
|
||||
# install the runtimes (parsed from json!)
|
||||
repo = 'flathub'
|
||||
repo_url = 'https://dl.flathub.org/repo/flathub.flatpakrepo'
|
||||
repo = "flathub"
|
||||
repo_url = "https://dl.flathub.org/repo/flathub.flatpakrepo"
|
||||
print("Installing dependencies")
|
||||
cmd = ['flatpak', 'remote-add', '--if-not-exists', repo, repo_url]
|
||||
cmd = ["flatpak", "remote-add", "--if-not-exists", repo, repo_url]
|
||||
subprocess.run(cmd, check=True)
|
||||
cmd = ['flatpak', 'install', '--assumeyes', repo, sdk]
|
||||
cmd = ["flatpak", "install", "--assumeyes", repo, sdk]
|
||||
subprocess.run(cmd, check=True)
|
||||
cmd = ['flatpak', 'install', '--assumeyes', repo, platform]
|
||||
cmd = ["flatpak", "install", "--assumeyes", repo, platform]
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
|
||||
def build(target):
|
||||
cmd = [
|
||||
'flatpak-builder',
|
||||
'--repo=repo',
|
||||
'--force-clean',
|
||||
'--disable-rofiles-fuse',
|
||||
'build-dir',
|
||||
"flatpak-builder",
|
||||
"--repo=repo",
|
||||
"--force-clean",
|
||||
"--disable-rofiles-fuse",
|
||||
"build-dir",
|
||||
target,
|
||||
]
|
||||
subprocess.run(cmd, check=True)
|
||||
cmd = ['flatpak', 'build-bundle', 'repo', 'fwupd.flatpak', 'org.freedesktop.fwupd']
|
||||
cmd = ["flatpak", "build-bundle", "repo", "fwupd.flatpak", "org.freedesktop.fwupd"]
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
t = os.path.join('build', 'org.freedesktop.fwupd.json')
|
||||
if __name__ == "__main__":
|
||||
t = os.path.join("build", "org.freedesktop.fwupd.json")
|
||||
prepare(t)
|
||||
build(t)
|
||||
|
||||
|
@ -10,25 +10,25 @@ import xml.etree.ElementTree as etree
|
||||
|
||||
|
||||
def parse_control_dependencies(requested_type):
|
||||
TARGET = os.getenv('OS')
|
||||
QUBES = os.getenv('QUBES')
|
||||
TARGET = os.getenv("OS")
|
||||
QUBES = os.getenv("QUBES")
|
||||
deps = []
|
||||
dep = ''
|
||||
dep = ""
|
||||
|
||||
if TARGET == '':
|
||||
if TARGET == "":
|
||||
print("Missing OS environment variable")
|
||||
sys.exit(1)
|
||||
OS = TARGET
|
||||
SUBOS = ''
|
||||
SUBOS = ""
|
||||
if TARGET:
|
||||
split = TARGET.split('-')
|
||||
split = TARGET.split("-")
|
||||
if len(split) >= 2:
|
||||
OS = split[0]
|
||||
SUBOS = split[1]
|
||||
else:
|
||||
import lsb_release
|
||||
|
||||
OS = lsb_release.get_distro_information()['ID'].lower()
|
||||
OS = lsb_release.get_distro_information()["ID"].lower()
|
||||
import platform
|
||||
|
||||
SUBOS = platform.machine()
|
||||
@ -49,33 +49,33 @@ def parse_control_dependencies(requested_type):
|
||||
packages = distro.findall("package")
|
||||
for package in packages:
|
||||
if SUBOS:
|
||||
if not 'variant' in package.attrib:
|
||||
if not "variant" in package.attrib:
|
||||
continue
|
||||
if package.attrib['variant'] != SUBOS:
|
||||
if package.attrib["variant"] != SUBOS:
|
||||
continue
|
||||
if package.text:
|
||||
dep = package.text
|
||||
else:
|
||||
dep = child.attrib["id"]
|
||||
if child.attrib["type"] == requested_type and dep:
|
||||
version = control.find('version')
|
||||
version = control.find("version")
|
||||
if version is not None:
|
||||
dep = "%s %s" % (dep, version.text)
|
||||
inclusions = control.findall('inclusive')
|
||||
inclusions = control.findall("inclusive")
|
||||
if inclusions:
|
||||
for i in range(0, len(inclusions)):
|
||||
prefix = ''
|
||||
suffix = ' '
|
||||
prefix = ""
|
||||
suffix = " "
|
||||
if i == 0:
|
||||
prefix = " ["
|
||||
if i == len(inclusions) - 1:
|
||||
suffix = "]"
|
||||
dep = "%s%s%s%s" % (dep, prefix, inclusions[i].text, suffix)
|
||||
exclusions = control.findall('exclusive')
|
||||
exclusions = control.findall("exclusive")
|
||||
if exclusions:
|
||||
for i in range(0, len(exclusions)):
|
||||
prefix = '!'
|
||||
suffix = ' '
|
||||
prefix = "!"
|
||||
suffix = " "
|
||||
if i == 0:
|
||||
prefix = " [!"
|
||||
if i == len(exclusions) - 1:
|
||||
@ -86,26 +86,26 @@ def parse_control_dependencies(requested_type):
|
||||
|
||||
|
||||
def update_debian_control(target):
|
||||
control_in = os.path.join(target, 'control.in')
|
||||
control_out = os.path.join(target, 'control')
|
||||
control_in = os.path.join(target, "control.in")
|
||||
control_out = os.path.join(target, "control")
|
||||
|
||||
if not os.path.exists(control_in):
|
||||
print("Missing file %s" % control_in)
|
||||
sys.exit(1)
|
||||
|
||||
with open(control_in, 'r') as rfd:
|
||||
with open(control_in, "r") as rfd:
|
||||
lines = rfd.readlines()
|
||||
|
||||
deps, QUBES = parse_control_dependencies("build")
|
||||
deps.sort()
|
||||
|
||||
if QUBES:
|
||||
lines += '\n'
|
||||
control_qubes_in = os.path.join(target, 'control.qubes.in')
|
||||
with open(control_qubes_in, 'r') as rfd:
|
||||
lines += "\n"
|
||||
control_qubes_in = os.path.join(target, "control.qubes.in")
|
||||
with open(control_qubes_in, "r") as rfd:
|
||||
lines += rfd.readlines()
|
||||
|
||||
with open(control_out, 'w') as wfd:
|
||||
with open(control_out, "w") as wfd:
|
||||
for line in lines:
|
||||
if line.startswith("Build-Depends: %%%DYNAMIC%%%"):
|
||||
wfd.write("Build-Depends:\n")
|
||||
@ -118,8 +118,8 @@ def update_debian_control(target):
|
||||
|
||||
|
||||
def update_debian_copyright(directory):
|
||||
copyright_in = os.path.join(directory, 'copyright.in')
|
||||
copyright_out = os.path.join(directory, 'copyright')
|
||||
copyright_in = os.path.join(directory, "copyright.in")
|
||||
copyright_out = os.path.join(directory, "copyright")
|
||||
|
||||
if not os.path.exists(copyright_in):
|
||||
print("Missing file %s" % copyright_in)
|
||||
@ -127,14 +127,14 @@ def update_debian_copyright(directory):
|
||||
|
||||
# Assume all files are remaining LGPL-2.1+
|
||||
copyrights = []
|
||||
for root, dirs, files in os.walk('.'):
|
||||
for root, dirs, files in os.walk("."):
|
||||
for file in files:
|
||||
target = os.path.join(root, file)
|
||||
# skip translations and license file
|
||||
if target.startswith('./po/') or file == "COPYING":
|
||||
if target.startswith("./po/") or file == "COPYING":
|
||||
continue
|
||||
try:
|
||||
with open(target, 'r') as rfd:
|
||||
with open(target, "r") as rfd:
|
||||
# read about the first few lines of the file only
|
||||
lines = rfd.readlines(220)
|
||||
except UnicodeDecodeError:
|
||||
@ -142,17 +142,17 @@ def update_debian_copyright(directory):
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
for line in lines:
|
||||
if 'Copyright (C) ' in line:
|
||||
parts = line.split('Copyright (C)')[
|
||||
if "Copyright (C) " in line:
|
||||
parts = line.split("Copyright (C)")[
|
||||
1
|
||||
].strip() # split out the copyright header
|
||||
partition = parts.partition(' ')[2] # remove the year string
|
||||
partition = parts.partition(" ")[2] # remove the year string
|
||||
copyrights += ["%s" % partition]
|
||||
copyrights = "\n\t ".join(sorted(set(copyrights)))
|
||||
with open(copyright_in, 'r') as rfd:
|
||||
with open(copyright_in, "r") as rfd:
|
||||
lines = rfd.readlines()
|
||||
|
||||
with open(copyright_out, 'w') as wfd:
|
||||
with open(copyright_out, "w") as wfd:
|
||||
for line in lines:
|
||||
if line.startswith("%%%DYNAMIC%%%"):
|
||||
wfd.write("Files: *\n")
|
||||
@ -163,6 +163,6 @@ def update_debian_copyright(directory):
|
||||
wfd.write(line)
|
||||
|
||||
|
||||
directory = os.path.join(os.getcwd(), 'debian')
|
||||
directory = os.path.join(os.getcwd(), "debian")
|
||||
update_debian_control(directory)
|
||||
update_debian_copyright(directory)
|
||||
|
@ -13,7 +13,7 @@ import xml.etree.ElementTree as etree
|
||||
|
||||
def parse_dependencies(OS, SUBOS, requested_type):
|
||||
deps = []
|
||||
dep = ''
|
||||
dep = ""
|
||||
directory = os.path.dirname(sys.argv[0])
|
||||
tree = etree.parse(os.path.join(directory, "dependencies.xml"))
|
||||
root = tree.getroot()
|
||||
@ -28,9 +28,9 @@ def parse_dependencies(OS, SUBOS, requested_type):
|
||||
packages = distro.findall("package")
|
||||
for package in packages:
|
||||
if SUBOS:
|
||||
if 'variant' not in package.attrib:
|
||||
if "variant" not in package.attrib:
|
||||
continue
|
||||
if package.attrib['variant'] != SUBOS:
|
||||
if package.attrib["variant"] != SUBOS:
|
||||
continue
|
||||
if package.text:
|
||||
dep = package.text
|
||||
@ -41,7 +41,7 @@ def parse_dependencies(OS, SUBOS, requested_type):
|
||||
return deps
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
|
||||
try:
|
||||
import distro
|
||||
@ -60,15 +60,15 @@ if __name__ == '__main__':
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
target = os.getenv('OS', args.os)
|
||||
target = os.getenv("OS", args.os)
|
||||
if target is None:
|
||||
print("Missing OS environment variable")
|
||||
sys.exit(1)
|
||||
|
||||
_os = target.lower()
|
||||
_sub_os = ''
|
||||
split = target.split('-')
|
||||
_sub_os = ""
|
||||
split = target.split("-")
|
||||
if len(split) >= 2:
|
||||
_os, _sub_os = split[:2]
|
||||
dependencies = parse_dependencies(_os, _sub_os, "build")
|
||||
print(*dependencies, sep='\n')
|
||||
print(*dependencies, sep="\n")
|
||||
|
@ -12,23 +12,23 @@ from generate_dependencies import parse_dependencies
|
||||
|
||||
|
||||
def get_container_cmd():
|
||||
'''return docker or podman as container manager'''
|
||||
"""return docker or podman as container manager"""
|
||||
|
||||
if shutil.which('docker'):
|
||||
return 'docker'
|
||||
if shutil.which('podman'):
|
||||
return 'podman'
|
||||
if shutil.which("docker"):
|
||||
return "docker"
|
||||
if shutil.which("podman"):
|
||||
return "podman"
|
||||
|
||||
|
||||
directory = os.path.dirname(sys.argv[0])
|
||||
TARGET = os.getenv('OS')
|
||||
TARGET = os.getenv("OS")
|
||||
|
||||
if TARGET is None:
|
||||
print("Missing OS environment variable")
|
||||
sys.exit(1)
|
||||
OS = TARGET
|
||||
SUBOS = ''
|
||||
split = TARGET.split('-')
|
||||
SUBOS = ""
|
||||
split = TARGET.split("-")
|
||||
if len(split) >= 2:
|
||||
OS = split[0]
|
||||
SUBOS = split[1]
|
||||
@ -40,19 +40,19 @@ if not os.path.exists(input):
|
||||
print("Missing input file %s for %s" % (input, OS))
|
||||
sys.exit(1)
|
||||
|
||||
with open(input, 'r') as rfd:
|
||||
with open(input, "r") as rfd:
|
||||
lines = rfd.readlines()
|
||||
|
||||
with open('Dockerfile', 'w') as wfd:
|
||||
with open("Dockerfile", "w") as wfd:
|
||||
for line in lines:
|
||||
if line.startswith("FROM %%%ARCH_PREFIX%%%"):
|
||||
if (OS == "debian" or OS == "ubuntu") and SUBOS == "i386":
|
||||
replace = SUBOS + "/"
|
||||
else:
|
||||
replace = ''
|
||||
replace = ""
|
||||
wfd.write(line.replace("%%%ARCH_PREFIX%%%", replace))
|
||||
elif line == "%%%INSTALL_DEPENDENCIES_COMMAND%%%\n":
|
||||
if OS == "fedora" or OS == 'flatpak':
|
||||
if OS == "fedora" or OS == "flatpak":
|
||||
wfd.write("RUN dnf --enablerepo=updates-testing -y install \\\n")
|
||||
elif OS == "centos":
|
||||
wfd.write("RUN yum -y install \\\n")
|
||||
@ -75,19 +75,19 @@ with open('Dockerfile', 'w') as wfd:
|
||||
'RUN cat /etc/apt/sources.list | sed "s/deb/deb-src/" >> /etc/apt/sources.list\n'
|
||||
)
|
||||
# add new architecture
|
||||
wfd.write('RUN dpkg --add-architecture %s\n' % SUBOS)
|
||||
wfd.write("RUN dpkg --add-architecture %s\n" % SUBOS)
|
||||
elif line == "%%%OS%%%\n":
|
||||
wfd.write("ENV OS %s\n" % TARGET)
|
||||
else:
|
||||
wfd.write(line)
|
||||
wfd.flush()
|
||||
|
||||
if len(sys.argv) == 2 and sys.argv[1] == 'build':
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "build":
|
||||
cmd = get_container_cmd()
|
||||
args = [cmd, "build", "-t", "fwupd-%s" % TARGET]
|
||||
if 'http_proxy' in os.environ:
|
||||
args += ['--build-arg=http_proxy=%s' % os.environ['http_proxy']]
|
||||
if 'https_proxy' in os.environ:
|
||||
args += ['--build-arg=https_proxy=%s' % os.environ['https_proxy']]
|
||||
if "http_proxy" in os.environ:
|
||||
args += ["--build-arg=http_proxy=%s" % os.environ["http_proxy"]]
|
||||
if "https_proxy" in os.environ:
|
||||
args += ["--build-arg=https_proxy=%s" % os.environ["https_proxy"]]
|
||||
args += ["-f", "./Dockerfile", "."]
|
||||
subprocess.check_call(args)
|
||||
|
@ -119,14 +119,7 @@ class Builder:
|
||||
if not os.path.exists(fullsrc):
|
||||
fullsrc = os.path.join(self.builddir, src)
|
||||
dst = os.path.basename(src).replace(".c", ".o")
|
||||
argv.extend(
|
||||
[
|
||||
"-c",
|
||||
fullsrc,
|
||||
"-o",
|
||||
os.path.join(self.builddir, dst),
|
||||
]
|
||||
)
|
||||
argv.extend(["-c", fullsrc, "-o", os.path.join(self.builddir, dst)])
|
||||
print("building {} into {}".format(src, dst))
|
||||
try:
|
||||
subprocess.run(argv, cwd=self.srcdir, check=True)
|
||||
@ -169,11 +162,9 @@ class Builder:
|
||||
|
||||
def makezip(self, dst: str, globstr: str) -> None:
|
||||
""" create a zip file archive from a glob """
|
||||
argv = [
|
||||
"zip",
|
||||
"--junk-paths",
|
||||
os.path.join(self.installdir, dst),
|
||||
] + glob.glob(os.path.join(self.srcdir, globstr))
|
||||
argv = ["zip", "--junk-paths", os.path.join(self.installdir, dst)] + glob.glob(
|
||||
os.path.join(self.srcdir, globstr)
|
||||
)
|
||||
print("assembling {}".format(dst))
|
||||
subprocess.run(argv, cwd=self.srcdir, check=True)
|
||||
|
||||
@ -240,16 +231,10 @@ def _build(bld: Builder) -> None:
|
||||
|
||||
# JSON-GLib
|
||||
src = bld.checkout_source(
|
||||
"json-glib",
|
||||
url="https://gitlab.gnome.org/GNOME/json-glib.git",
|
||||
"json-glib", url="https://gitlab.gnome.org/GNOME/json-glib.git"
|
||||
)
|
||||
bld.build_meson_project(
|
||||
src,
|
||||
[
|
||||
"-Dgtk_doc=disabled",
|
||||
"-Dtests=false",
|
||||
"-Dintrospection=disabled",
|
||||
],
|
||||
src, ["-Dgtk_doc=disabled", "-Dtests=false", "-Dintrospection=disabled"]
|
||||
)
|
||||
bld.add_work_includedir("include/json-glib-1.0/json-glib")
|
||||
bld.add_work_includedir("include/json-glib-1.0")
|
||||
@ -258,12 +243,7 @@ def _build(bld: Builder) -> None:
|
||||
# libxmlb
|
||||
src = bld.checkout_source("libxmlb", url="https://github.com/hughsie/libxmlb.git")
|
||||
bld.build_meson_project(
|
||||
src,
|
||||
[
|
||||
"-Dgtkdoc=false",
|
||||
"-Dintrospection=false",
|
||||
"-Dtests=false",
|
||||
],
|
||||
src, ["-Dgtkdoc=false", "-Dintrospection=false", "-Dtests=false"]
|
||||
)
|
||||
bld.add_work_includedir("include/libxmlb-2")
|
||||
bld.add_work_includedir("include/libxmlb-2/libxmlb")
|
||||
|
@ -24,26 +24,26 @@ def add_header(infile, outfile, gd, fl=None):
|
||||
import struct
|
||||
|
||||
try:
|
||||
with open(infile, 'rb') as f:
|
||||
with open(infile, "rb") as f:
|
||||
bin_data = f.read()
|
||||
except FileNotFoundError as e:
|
||||
print(e)
|
||||
return 1
|
||||
|
||||
# check if already has header
|
||||
hdrsz = struct.calcsize('<16sIII')
|
||||
hdrsz = struct.calcsize("<16sIII")
|
||||
if len(bin_data) >= hdrsz:
|
||||
hdr = struct.unpack('<16sIII', bin_data[:hdrsz])
|
||||
hdr = struct.unpack("<16sIII", bin_data[:hdrsz])
|
||||
imgsz = hdr[3]
|
||||
if imgsz == len(bin_data):
|
||||
print('Replacing existing CAPSULE_HEADER of:')
|
||||
print("Replacing existing CAPSULE_HEADER of:")
|
||||
guid_mixed = uuid.UUID(bytes_le=hdr[0])
|
||||
hdrsz_old = hdr[1]
|
||||
flags = hdr[2]
|
||||
print('GUID: %s' % guid_mixed)
|
||||
print('HdrSz: 0x%04x' % hdrsz_old)
|
||||
print('Flags: 0x%04x' % flags)
|
||||
print('PayloadSz: 0x%04x' % imgsz)
|
||||
print("GUID: %s" % guid_mixed)
|
||||
print("HdrSz: 0x%04x" % hdrsz_old)
|
||||
print("Flags: 0x%04x" % flags)
|
||||
print("PayloadSz: 0x%04x" % imgsz)
|
||||
bin_data = bin_data[hdrsz_old:]
|
||||
|
||||
# set header flags
|
||||
@ -59,24 +59,24 @@ def add_header(infile, outfile, gd, fl=None):
|
||||
hdrsz = 4096
|
||||
imgsz = hdrsz + len(bin_data)
|
||||
hdr = ctypes.create_string_buffer(hdrsz)
|
||||
struct.pack_into('<16sIII', hdr, 0, guid.bytes_le, hdrsz, flags, imgsz)
|
||||
with open(outfile, 'wb') as f:
|
||||
struct.pack_into("<16sIII", hdr, 0, guid.bytes_le, hdrsz, flags, imgsz)
|
||||
with open(outfile, "wb") as f:
|
||||
f.write(hdr)
|
||||
f.write(bin_data)
|
||||
print('Wrote capsule %s' % outfile)
|
||||
print('GUID: %s' % guid)
|
||||
print('HdrSz: 0x%04x' % hdrsz)
|
||||
print('Flags: 0x%04x' % flags)
|
||||
print('PayloadSz: 0x%04x' % imgsz)
|
||||
print("Wrote capsule %s" % outfile)
|
||||
print("GUID: %s" % guid)
|
||||
print("HdrSz: 0x%04x" % hdrsz)
|
||||
print("Flags: 0x%04x" % flags)
|
||||
print("PayloadSz: 0x%04x" % imgsz)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Add capsule header on firmware')
|
||||
parser.add_argument('--guid', help='GUID of the device', required=True)
|
||||
parser.add_argument('--bin', help='Path to the .bin file', required=True)
|
||||
parser.add_argument('--cap', help='Output capsule file path', required=True)
|
||||
parser.add_argument('--flags', help='Flags, e.g. 0x40000', default=None)
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Add capsule header on firmware")
|
||||
parser.add_argument("--guid", help="GUID of the device", required=True)
|
||||
parser.add_argument("--bin", help="Path to the .bin file", required=True)
|
||||
parser.add_argument("--cap", help="Output capsule file path", required=True)
|
||||
parser.add_argument("--flags", help="Flags, e.g. 0x40000", default=None)
|
||||
args = parser.parse_args()
|
||||
|
||||
sys.exit(add_header(args.bin, args.cap, args.guid, args.flags))
|
||||
|
@ -13,43 +13,43 @@ import argparse
|
||||
def main(bin_fn, dfu_fn, pad, vid, pid, rev):
|
||||
|
||||
# read binary file
|
||||
with open(bin_fn, 'rb') as f:
|
||||
with open(bin_fn, "rb") as f:
|
||||
blob = f.read()
|
||||
|
||||
# pad blob to a specific size
|
||||
if pad:
|
||||
while len(blob) < int(pad, 16):
|
||||
blob += b'\0'
|
||||
blob += b"\0"
|
||||
|
||||
# create DFU footer with checksum
|
||||
blob += struct.pack(
|
||||
'<HHHH3sB',
|
||||
"<HHHH3sB",
|
||||
int(rev, 16), # version
|
||||
int(pid, 16), # PID
|
||||
int(vid, 16), # VID
|
||||
0x0100, # DFU version
|
||||
b'UFD', # signature
|
||||
b"UFD", # signature
|
||||
0x10,
|
||||
) # hdrlen
|
||||
crc32 = zlib.crc32(blob) ^ 0xFFFFFFFF
|
||||
blob += struct.pack('<L', crc32)
|
||||
blob += struct.pack("<L", crc32)
|
||||
|
||||
# write binary file
|
||||
with open(dfu_fn, 'wb') as f:
|
||||
with open(dfu_fn, "wb") as f:
|
||||
f.write(blob)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# parse args
|
||||
parser = argparse.ArgumentParser(description='Add DFU footer on firmware')
|
||||
parser.add_argument('--bin', help='Path to the .bin file', required=True)
|
||||
parser.add_argument('--dfu', help='Output DFU file path', required=True)
|
||||
parser = argparse.ArgumentParser(description="Add DFU footer on firmware")
|
||||
parser.add_argument("--bin", help="Path to the .bin file", required=True)
|
||||
parser.add_argument("--dfu", help="Output DFU file path", required=True)
|
||||
parser.add_argument(
|
||||
'--pad', help='Pad to a specific size, e.g. 0x4000', default=None
|
||||
"--pad", help="Pad to a specific size, e.g. 0x4000", default=None
|
||||
)
|
||||
parser.add_argument('--vid', help='Vendor ID, e.g. 0x273f', required=True)
|
||||
parser.add_argument('--pid', help='Product ID, e.g. 0x1002', required=True)
|
||||
parser.add_argument('--rev', help='Revision, e.g. 0x1000', required=True)
|
||||
parser.add_argument("--vid", help="Vendor ID, e.g. 0x273f", required=True)
|
||||
parser.add_argument("--pid", help="Product ID, e.g. 0x1002", required=True)
|
||||
parser.add_argument("--rev", help="Revision, e.g. 0x1000", required=True)
|
||||
args = parser.parse_args()
|
||||
main(args.bin, args.dfu, args.pad, args.vid, args.pid, args.rev)
|
||||
|
@ -57,107 +57,107 @@ def make_firmware_metainfo(firmware_info, dst):
|
||||
**local_info, timestamp=time.time()
|
||||
)
|
||||
|
||||
with open(os.path.join(dst, 'firmware.metainfo.xml'), 'w') as f:
|
||||
with open(os.path.join(dst, "firmware.metainfo.xml"), "w") as f:
|
||||
f.write(firmware_metainfo)
|
||||
|
||||
|
||||
def extract_exe(exe, dst):
|
||||
command = ['7z', 'x', '-o{}'.format(dst), exe]
|
||||
command = ["7z", "x", "-o{}".format(dst), exe]
|
||||
subprocess.check_call(command, stdout=subprocess.DEVNULL)
|
||||
|
||||
|
||||
def get_firmware_bin(root, bin_path, dst):
|
||||
with cd(root):
|
||||
shutil.copy(bin_path, os.path.join(dst, 'firmware.bin'))
|
||||
shutil.copy(bin_path, os.path.join(dst, "firmware.bin"))
|
||||
|
||||
|
||||
def create_firmware_cab(exe, folder):
|
||||
with cd(folder):
|
||||
if os.name == "nt":
|
||||
directive = os.path.join(folder, "directive")
|
||||
with open(directive, 'w') as wfd:
|
||||
wfd.write('.OPTION EXPLICIT\r\n')
|
||||
wfd.write('.Set CabinetNameTemplate=firmware.cab\r\n')
|
||||
wfd.write('.Set DiskDirectory1=.\r\n')
|
||||
wfd.write('firmware.bin\r\n')
|
||||
wfd.write('firmware.metainfo.xml\r\n')
|
||||
command = ['makecab.exe', '/f', directive]
|
||||
with open(directive, "w") as wfd:
|
||||
wfd.write(".OPTION EXPLICIT\r\n")
|
||||
wfd.write(".Set CabinetNameTemplate=firmware.cab\r\n")
|
||||
wfd.write(".Set DiskDirectory1=.\r\n")
|
||||
wfd.write("firmware.bin\r\n")
|
||||
wfd.write("firmware.metainfo.xml\r\n")
|
||||
command = ["makecab.exe", "/f", directive]
|
||||
else:
|
||||
command = [
|
||||
'gcab',
|
||||
'--create',
|
||||
'firmware.cab',
|
||||
'firmware.bin',
|
||||
'firmware.metainfo.xml',
|
||||
"gcab",
|
||||
"--create",
|
||||
"firmware.cab",
|
||||
"firmware.bin",
|
||||
"firmware.metainfo.xml",
|
||||
]
|
||||
subprocess.check_call(command)
|
||||
|
||||
|
||||
def main(args):
|
||||
with tempfile.TemporaryDirectory() as dir:
|
||||
print('Using temp directory {}'.format(dir))
|
||||
print("Using temp directory {}".format(dir))
|
||||
|
||||
if args.exe:
|
||||
print('Extracting firmware exe')
|
||||
print("Extracting firmware exe")
|
||||
extract_exe(args.exe, dir)
|
||||
|
||||
print('Locating firmware bin')
|
||||
print("Locating firmware bin")
|
||||
get_firmware_bin(dir, args.bin, dir)
|
||||
|
||||
print('Creating metainfo')
|
||||
print("Creating metainfo")
|
||||
make_firmware_metainfo(args, dir)
|
||||
|
||||
print('Creating cabinet file')
|
||||
print("Creating cabinet file")
|
||||
create_firmware_cab(args, dir)
|
||||
|
||||
print('Done')
|
||||
shutil.copy(os.path.join(dir, 'firmware.cab'), args.out)
|
||||
print("Done")
|
||||
shutil.copy(os.path.join(dir, "firmware.cab"), args.out)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Create fwupd packaged from windows executables'
|
||||
description="Create fwupd packaged from windows executables"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--firmware-name',
|
||||
help='Name of the firmware package can be customized (e.g. DellTBT)',
|
||||
"--firmware-name",
|
||||
help="Name of the firmware package can be customized (e.g. DellTBT)",
|
||||
required=True,
|
||||
)
|
||||
parser.add_argument(
|
||||
'--firmware-summary', help='One line description of the firmware package'
|
||||
"--firmware-summary", help="One line description of the firmware package"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--firmware-description', help='Longer description of the firmware package'
|
||||
"--firmware-description", help="Longer description of the firmware package"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--device-guid',
|
||||
help='GUID of the device this firmware will run on, this *must* match the output of one of the GUIDs in `fwupdmgr get-devices`',
|
||||
"--device-guid",
|
||||
help="GUID of the device this firmware will run on, this *must* match the output of one of the GUIDs in `fwupdmgr get-devices`",
|
||||
required=True,
|
||||
)
|
||||
parser.add_argument('--firmware-homepage', help='Website for the firmware provider')
|
||||
parser.add_argument("--firmware-homepage", help="Website for the firmware provider")
|
||||
parser.add_argument(
|
||||
'--contact-info', help='Email address of the firmware developer'
|
||||
"--contact-info", help="Email address of the firmware developer"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--developer-name', help='Name of the firmware developer', required=True
|
||||
"--developer-name", help="Name of the firmware developer", required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'--release-version',
|
||||
help='Version number of the firmware package',
|
||||
"--release-version",
|
||||
help="Version number of the firmware package",
|
||||
required=True,
|
||||
)
|
||||
parser.add_argument(
|
||||
'--release-description', help='Description of the firmware release'
|
||||
"--release-description", help="Description of the firmware release"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--exe', help='(optional) Executable file to extract firmware from'
|
||||
"--exe", help="(optional) Executable file to extract firmware from"
|
||||
)
|
||||
parser.add_argument(
|
||||
'--bin',
|
||||
help='Path to the .bin file (Relative if inside the executable; Absolute if outside) to use as the firmware image',
|
||||
"--bin",
|
||||
help="Path to the .bin file (Relative if inside the executable; Absolute if outside) to use as the firmware image",
|
||||
required=True,
|
||||
)
|
||||
parser.add_argument('--out', help='Output cab file path', required=True)
|
||||
parser.add_argument("--out", help="Output cab file path", required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args)
|
||||
|
@ -11,7 +11,7 @@ import tempfile
|
||||
import gi
|
||||
|
||||
try:
|
||||
gi.require_version('Fwupd', '2.0')
|
||||
gi.require_version("Fwupd", "2.0")
|
||||
except ValueError:
|
||||
print("Missing gobject-introspection packages. Try to install gir1.2-fwupd-2.0.")
|
||||
sys.exit(1)
|
||||
@ -39,8 +39,8 @@ def parse_args():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Interact with fwupd daemon")
|
||||
parser.add_argument('exe', nargs='?', help='exe file')
|
||||
parser.add_argument('deviceid', nargs='?', help='DeviceID to operate on(optional)')
|
||||
parser.add_argument("exe", nargs="?", help="exe file")
|
||||
parser.add_argument("deviceid", nargs="?", help="DeviceID to operate on(optional)")
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
@ -72,7 +72,7 @@ def find_uefi_device(client, deviceid):
|
||||
if not item.has_flag(1 << 8):
|
||||
continue
|
||||
# return the first hit for UEFI plugin
|
||||
if item.get_plugin() == 'uefi' or item.get_plugin() == 'uefi_capsule':
|
||||
if item.get_plugin() == "uefi" or item.get_plugin() == "uefi_capsule":
|
||||
print("Installing to %s" % item.get_name())
|
||||
return item.get_guid_default(), item.get_id(), item.get_version()
|
||||
print("Couldn't find any UEFI devices")
|
||||
@ -83,19 +83,19 @@ def prompt_reboot():
|
||||
print("An update requires a reboot to complete")
|
||||
while True:
|
||||
res = input("Restart now? (Y/N) ")
|
||||
if res.lower() == 'n':
|
||||
if res.lower() == "n":
|
||||
print("Reboot your machine manually to finish the update.")
|
||||
break
|
||||
if res.lower() != 'y':
|
||||
if res.lower() != "y":
|
||||
continue
|
||||
# reboot using logind
|
||||
obj = dbus.SystemBus().get_object(
|
||||
'org.freedesktop.login1', '/org/freedesktop/login1'
|
||||
"org.freedesktop.login1", "/org/freedesktop/login1"
|
||||
)
|
||||
obj.Reboot(True, dbus_interface='org.freedesktop.login1.Manager')
|
||||
obj.Reboot(True, dbus_interface="org.freedesktop.login1.Manager")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
ARGS = parse_args()
|
||||
CLIENT = Fwupd.Client()
|
||||
CLIENT.connect()
|
||||
|
@ -6,7 +6,7 @@ import os
|
||||
import gi
|
||||
from gi.repository import GLib
|
||||
|
||||
gi.require_version('Fwupd', '2.0')
|
||||
gi.require_version("Fwupd", "2.0")
|
||||
from gi.repository import Fwupd # pylint: disable=wrong-import-position
|
||||
|
||||
|
||||
@ -35,14 +35,14 @@ class Progress:
|
||||
status_str = "["
|
||||
for i in range(0, 50):
|
||||
if i < percent / 2:
|
||||
status_str += '*'
|
||||
status_str += "*"
|
||||
else:
|
||||
status_str += ' '
|
||||
status_str += " "
|
||||
status_str += "] %d%% %s" % (percent, status)
|
||||
self.erase = len(status_str)
|
||||
sys.stdout.write(status_str)
|
||||
sys.stdout.flush()
|
||||
if 'idle' in status:
|
||||
if "idle" in status:
|
||||
sys.stdout.write("\n")
|
||||
|
||||
|
||||
@ -66,8 +66,8 @@ def parse_args():
|
||||
choices=["get-devices", "get-details", "install", "refresh"],
|
||||
help="What to do",
|
||||
)
|
||||
parser.add_argument('cab', nargs='?', help='CAB file')
|
||||
parser.add_argument('deviceid', nargs='?', help='DeviceID to operate on(optional)')
|
||||
parser.add_argument("cab", nargs="?", help="CAB file")
|
||||
parser.add_argument("deviceid", nargs="?", help="DeviceID to operate on(optional)")
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
@ -114,7 +114,7 @@ def install(client, cab, target, older, reinstall):
|
||||
"""Use fwupd client to install CAB file to applicable devices"""
|
||||
# FWUPD_DEVICE_ID_ANY
|
||||
if not target:
|
||||
target = '*'
|
||||
target = "*"
|
||||
flags = Fwupd.InstallFlags.NONE
|
||||
if older:
|
||||
flags |= Fwupd.InstallFlags.ALLOW_OLDER
|
||||
@ -122,13 +122,13 @@ def install(client, cab, target, older, reinstall):
|
||||
flags |= Fwupd.InstallFlags.ALLOW_REINSTALL
|
||||
progress = Progress()
|
||||
parent = super(client.__class__, client)
|
||||
parent.connect('device-changed', device_changed, progress)
|
||||
parent.connect('notify::percentage', status_changed, progress)
|
||||
parent.connect('notify::status', status_changed, progress)
|
||||
parent.connect("device-changed", device_changed, progress)
|
||||
parent.connect("notify::percentage", status_changed, progress)
|
||||
parent.connect("notify::status", status_changed, progress)
|
||||
try:
|
||||
client.install(target, cab, flags, None)
|
||||
except GLib.Error as glib_err: # pylint: disable=catching-non-exception
|
||||
progress.status_changed(0, 'idle')
|
||||
progress.status_changed(0, "idle")
|
||||
print("%s" % glib_err)
|
||||
sys.exit(1)
|
||||
print("\n")
|
||||
@ -144,7 +144,7 @@ def check_exists(cab):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
ARGS = parse_args()
|
||||
CLIENT = Fwupd.Client()
|
||||
CLIENT.connect()
|
||||
|
@ -8,13 +8,13 @@ import subprocess
|
||||
|
||||
def _do_msgattrib(fn):
|
||||
argv = [
|
||||
'msgattrib',
|
||||
'--no-location',
|
||||
'--translated',
|
||||
'--no-wrap',
|
||||
'--sort-output',
|
||||
"msgattrib",
|
||||
"--no-location",
|
||||
"--translated",
|
||||
"--no-wrap",
|
||||
"--sort-output",
|
||||
fn,
|
||||
'--output-file=' + fn,
|
||||
"--output-file=" + fn,
|
||||
]
|
||||
ret = subprocess.run(argv)
|
||||
if ret.returncode != 0:
|
||||
@ -33,7 +33,7 @@ def _do_nukeheader(fn):
|
||||
if line.startswith('"Last-Translator:'):
|
||||
continue
|
||||
clean_lines.append(line)
|
||||
with open(fn, 'w') as f:
|
||||
with open(fn, "w") as f:
|
||||
f.writelines(clean_lines)
|
||||
|
||||
|
||||
@ -42,15 +42,15 @@ def _process_file(fn):
|
||||
_do_nukeheader(fn)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) == 1:
|
||||
print('path required')
|
||||
print("path required")
|
||||
sys.exit(1)
|
||||
try:
|
||||
dirname = sys.argv[1]
|
||||
for fn in os.listdir(dirname):
|
||||
if fn.endswith('.po'):
|
||||
if fn.endswith(".po"):
|
||||
_process_file(os.path.join(dirname, fn))
|
||||
except NotADirectoryError as _:
|
||||
print('path required')
|
||||
print("path required")
|
||||
sys.exit(2)
|
||||
|
@ -11,8 +11,8 @@ import xml.etree.ElementTree as ET
|
||||
|
||||
from pkg_resources import parse_version
|
||||
|
||||
XMLNS = '{http://www.gtk.org/introspection/core/1.0}'
|
||||
XMLNS_C = '{http://www.gtk.org/introspection/c/1.0}'
|
||||
XMLNS = "{http://www.gtk.org/introspection/core/1.0}"
|
||||
XMLNS_C = "{http://www.gtk.org/introspection/c/1.0}"
|
||||
|
||||
|
||||
def usage(return_code):
|
||||
@ -34,15 +34,15 @@ class LdVersionScript:
|
||||
self.overrides = {}
|
||||
|
||||
def _add_node(self, node):
|
||||
identifier = node.attrib[XMLNS_C + 'identifier']
|
||||
introspectable = int(node.get('introspectable', 1))
|
||||
version = node.get('version', None)
|
||||
identifier = node.attrib[XMLNS_C + "identifier"]
|
||||
introspectable = int(node.get("introspectable", 1))
|
||||
version = node.get("version", None)
|
||||
if introspectable and not version:
|
||||
print('No version for', identifier)
|
||||
print("No version for", identifier)
|
||||
sys.exit(1)
|
||||
if not version:
|
||||
return None
|
||||
version = node.attrib['version']
|
||||
version = node.attrib["version"]
|
||||
if version not in self.releases:
|
||||
self.releases[version] = []
|
||||
release = self.releases[version]
|
||||
@ -53,14 +53,14 @@ class LdVersionScript:
|
||||
def _add_cls(self, cls):
|
||||
|
||||
# add all class functions
|
||||
for node in cls.findall(XMLNS + 'function'):
|
||||
for node in cls.findall(XMLNS + "function"):
|
||||
self._add_node(node)
|
||||
|
||||
# choose the lowest version method for the _get_type symbol
|
||||
version_lowest = None
|
||||
|
||||
# add all class methods
|
||||
for node in cls.findall(XMLNS + 'method'):
|
||||
for node in cls.findall(XMLNS + "method"):
|
||||
version_tmp = self._add_node(node)
|
||||
if version_tmp:
|
||||
if not version_lowest or parse_version(version_tmp) < parse_version(
|
||||
@ -69,7 +69,7 @@ class LdVersionScript:
|
||||
version_lowest = version_tmp
|
||||
|
||||
# add the constructor
|
||||
for node in cls.findall(XMLNS + 'constructor'):
|
||||
for node in cls.findall(XMLNS + "constructor"):
|
||||
version_tmp = self._add_node(node)
|
||||
if version_tmp:
|
||||
if not version_lowest or parse_version(version_tmp) < parse_version(
|
||||
@ -77,9 +77,9 @@ class LdVersionScript:
|
||||
):
|
||||
version_lowest = version_tmp
|
||||
|
||||
if '{http://www.gtk.org/introspection/glib/1.0}get-type' not in cls.attrib:
|
||||
if "{http://www.gtk.org/introspection/glib/1.0}get-type" not in cls.attrib:
|
||||
return
|
||||
type_name = cls.attrib['{http://www.gtk.org/introspection/glib/1.0}get-type']
|
||||
type_name = cls.attrib["{http://www.gtk.org/introspection/glib/1.0}get-type"]
|
||||
|
||||
# finally add the get_type symbol
|
||||
version = self.overrides.get(type_name, version_lowest)
|
||||
@ -89,12 +89,12 @@ class LdVersionScript:
|
||||
def import_gir(self, filename):
|
||||
tree = ET.parse(filename)
|
||||
root = tree.getroot()
|
||||
for ns in root.findall(XMLNS + 'namespace'):
|
||||
for node in ns.findall(XMLNS + 'function'):
|
||||
for ns in root.findall(XMLNS + "namespace"):
|
||||
for node in ns.findall(XMLNS + "function"):
|
||||
self._add_node(node)
|
||||
for cls in ns.findall(XMLNS + 'record'):
|
||||
for cls in ns.findall(XMLNS + "record"):
|
||||
self._add_cls(cls)
|
||||
for cls in ns.findall(XMLNS + 'class'):
|
||||
for cls in ns.findall(XMLNS + "class"):
|
||||
self._add_cls(cls)
|
||||
|
||||
def render(self):
|
||||
@ -105,32 +105,28 @@ class LdVersionScript:
|
||||
versions.append(version)
|
||||
|
||||
# output the version data to a file
|
||||
verout = '# generated automatically, do not edit!\n'
|
||||
verout = "# generated automatically, do not edit!\n"
|
||||
oldversion = None
|
||||
for version in sorted(versions, key=parse_version):
|
||||
symbols = sorted(self.releases[version])
|
||||
verout += '\n%s_%s {\n' % (self.library_name, version)
|
||||
verout += ' global:\n'
|
||||
verout += "\n%s_%s {\n" % (self.library_name, version)
|
||||
verout += " global:\n"
|
||||
for symbol in symbols:
|
||||
verout += ' %s;\n' % symbol
|
||||
verout += ' local: *;\n'
|
||||
verout += " %s;\n" % symbol
|
||||
verout += " local: *;\n"
|
||||
if oldversion:
|
||||
verout += '} %s_%s;\n' % (self.library_name, oldversion)
|
||||
verout += "} %s_%s;\n" % (self.library_name, oldversion)
|
||||
else:
|
||||
verout += '};\n'
|
||||
verout += "};\n"
|
||||
oldversion = version
|
||||
return verout
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'-r',
|
||||
'--override',
|
||||
action='append',
|
||||
nargs=2,
|
||||
metavar=('symbol', 'version'),
|
||||
"-r", "--override", action="append", nargs=2, metavar=("symbol", "version")
|
||||
)
|
||||
args, argv = parser.parse_known_args()
|
||||
if len(argv) != 3:
|
||||
@ -141,4 +137,4 @@ if __name__ == '__main__':
|
||||
for override_symbol, override_version in args.override:
|
||||
ld.overrides[override_symbol] = override_version
|
||||
ld.import_gir(argv[1])
|
||||
open(argv[2], 'w').write(ld.render())
|
||||
open(argv[2], "w").write(ld.render())
|
||||
|
@ -20,26 +20,14 @@ FWUPD_DOM0_DIR = "/root/.cache/fwupd"
|
||||
FWUPD_DOM0_UPDATES_DIR = os.path.join(FWUPD_DOM0_DIR, "updates")
|
||||
FWUPD_DOM0_UNTRUSTED_DIR = os.path.join(FWUPD_DOM0_UPDATES_DIR, "untrusted")
|
||||
FWUPD_DOM0_METADATA_DIR = os.path.join(FWUPD_DOM0_DIR, "metadata")
|
||||
FWUPD_DOM0_METADATA_FILE = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
FWUPD_DOM0_METADATA_JCAT = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
"firmware.xml.gz.jcat"
|
||||
)
|
||||
FWUPD_DOM0_METADATA_FILE = os.path.join(FWUPD_DOM0_METADATA_DIR, "firmware.xml.gz")
|
||||
FWUPD_DOM0_METADATA_JCAT = os.path.join(FWUPD_DOM0_METADATA_DIR, "firmware.xml.gz.jcat")
|
||||
|
||||
FWUPD_VM_DIR = "/home/user/.cache/fwupd"
|
||||
FWUPD_VM_UPDATES_DIR = os.path.join(FWUPD_VM_DIR, "updates")
|
||||
FWUPD_VM_METADATA_DIR = os.path.join(FWUPD_VM_DIR, "metadata")
|
||||
FWUPD_VM_METADATA_FILE = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
FWUPD_VM_METADATA_JCAT = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz.jcat"
|
||||
)
|
||||
FWUPD_VM_METADATA_FILE = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz")
|
||||
FWUPD_VM_METADATA_JCAT = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz.jcat")
|
||||
FWUPD_PKI = "/etc/pki/fwupd"
|
||||
FWUPD_DOWNLOAD_PREFIX = "https://fwupd.org/downloads/"
|
||||
FWUPD_METADATA_FLAG_REGEX = re.compile(r"^metaflag")
|
||||
@ -47,7 +35,7 @@ FWUPD_METADATA_FILES_REGEX = re.compile(
|
||||
r"^firmware[a-z0-9\[\]\@\<\>\.\"\-]{0,128}.xml.gz.?[aj]?[sc]?[ca]?t?$"
|
||||
)
|
||||
HEADS_UPDATES_DIR = "/boot/updates"
|
||||
WARNING_COLOR = '\033[93m'
|
||||
WARNING_COLOR = "\033[93m"
|
||||
|
||||
|
||||
class FwupdReceiveUpdates:
|
||||
@ -58,7 +46,7 @@ class FwupdReceiveUpdates:
|
||||
file_path -- absolute path to the file
|
||||
sha -- SHA256 checksum of the file
|
||||
"""
|
||||
with open(file_path, 'rb') as f:
|
||||
with open(file_path, "rb") as f:
|
||||
c_sha = hashlib.sha256(f.read()).hexdigest()
|
||||
if c_sha != sha:
|
||||
self.clean_cache()
|
||||
@ -71,13 +59,11 @@ class FwupdReceiveUpdates:
|
||||
Keyword argument:
|
||||
updatevm - domain to be checked
|
||||
"""
|
||||
cmd = ['qubes-prefs', '--force-root', 'updatevm']
|
||||
cmd = ["qubes-prefs", "--force-root", "updatevm"]
|
||||
p = subprocess.check_output(cmd)
|
||||
source = p.decode('ascii').rstrip()
|
||||
source = p.decode("ascii").rstrip()
|
||||
if source != updatevm and "sys-whonix" != updatevm:
|
||||
raise Exception(
|
||||
f'Domain {updatevm} not allowed to send dom0 updates'
|
||||
)
|
||||
raise Exception(f"Domain {updatevm} not allowed to send dom0 updates")
|
||||
|
||||
def _verify_received(self, files_path, regex_pattern, updatevm):
|
||||
"""Checks if sent files match regex filename pattern.
|
||||
@ -90,14 +76,14 @@ class FwupdReceiveUpdates:
|
||||
"""
|
||||
for untrusted_f in os.listdir(files_path):
|
||||
if not regex_pattern.match(untrusted_f):
|
||||
raise Exception(f'Domain {updatevm} sent unexpected file')
|
||||
raise Exception(f"Domain {updatevm} sent unexpected file")
|
||||
f = untrusted_f
|
||||
assert '/' not in f
|
||||
assert '\0' not in f
|
||||
assert '\x1b' not in f
|
||||
assert "/" not in f
|
||||
assert "\0" not in f
|
||||
assert "\x1b" not in f
|
||||
path_f = os.path.join(files_path, f)
|
||||
if os.path.islink(path_f) or not os.path.isfile(path_f):
|
||||
raise Exception(f'Domain {updatevm} sent not regular file')
|
||||
raise Exception(f"Domain {updatevm} sent not regular file")
|
||||
|
||||
def _create_dirs(self, *args):
|
||||
"""Method creates directories.
|
||||
@ -105,7 +91,7 @@ class FwupdReceiveUpdates:
|
||||
Keyword arguments:
|
||||
*args -- paths to be created
|
||||
"""
|
||||
qubes_gid = grp.getgrnam('qubes').gr_gid
|
||||
qubes_gid = grp.getgrnam("qubes").gr_gid
|
||||
self.old_umask = os.umask(0o002)
|
||||
if args is None:
|
||||
raise Exception("Creating directories failed, no paths given.")
|
||||
@ -128,19 +114,12 @@ class FwupdReceiveUpdates:
|
||||
archive_path -- absolute path to archive file
|
||||
output_path -- absolute path to the output directory
|
||||
"""
|
||||
cmd_extract = [
|
||||
"gcab",
|
||||
"-x",
|
||||
f"--directory={output_path}",
|
||||
f"{archive_path}"
|
||||
]
|
||||
cmd_extract = ["gcab", "-x", f"--directory={output_path}", f"{archive_path}"]
|
||||
shutil.copy(archive_path, FWUPD_DOM0_UPDATES_DIR)
|
||||
p = subprocess.Popen(cmd_extract, stdout=subprocess.PIPE)
|
||||
p.communicate()[0].decode('ascii')
|
||||
p.communicate()[0].decode("ascii")
|
||||
if p.returncode != 0:
|
||||
raise Exception(
|
||||
f'gcab: Error while extracting {archive_path}.'
|
||||
)
|
||||
raise Exception(f"gcab: Error while extracting {archive_path}.")
|
||||
|
||||
def _jcat_verification(self, file_path, file_directory):
|
||||
"""Verifies sha1 and sha256 checksum, GPG signature,
|
||||
@ -150,25 +129,16 @@ class FwupdReceiveUpdates:
|
||||
file_path -- absolute path to jcat file
|
||||
file_directory -- absolute path to the directory to jcat file location
|
||||
"""
|
||||
cmd_jcat = [
|
||||
"jcat-tool",
|
||||
"verify",
|
||||
f"{file_path}",
|
||||
"--public-keys",
|
||||
FWUPD_PKI
|
||||
]
|
||||
cmd_jcat = ["jcat-tool", "verify", f"{file_path}", "--public-keys", FWUPD_PKI]
|
||||
p = subprocess.Popen(
|
||||
cmd_jcat,
|
||||
cwd=file_directory,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE
|
||||
cmd_jcat, cwd=file_directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
stdout, __ = p.communicate()
|
||||
verification = stdout.decode('utf-8')
|
||||
verification = stdout.decode("utf-8")
|
||||
print(verification)
|
||||
if p.returncode != 0:
|
||||
self.clean_cache()
|
||||
raise Exception('jcat-tool: Verification failed')
|
||||
raise Exception("jcat-tool: Verification failed")
|
||||
|
||||
def handle_fw_update(self, updatevm, sha, filename):
|
||||
"""Copies firmware update archives from the updateVM.
|
||||
@ -179,45 +149,31 @@ class FwupdReceiveUpdates:
|
||||
filename -- name of the firmware update archive
|
||||
"""
|
||||
fwupd_firmware_file_regex = re.compile(filename)
|
||||
dom0_firmware_untrusted_path = os.path.join(
|
||||
FWUPD_DOM0_UNTRUSTED_DIR,
|
||||
filename
|
||||
)
|
||||
updatevm_firmware_file_path = os.path.join(
|
||||
FWUPD_VM_UPDATES_DIR,
|
||||
filename
|
||||
)
|
||||
dom0_firmware_untrusted_path = os.path.join(FWUPD_DOM0_UNTRUSTED_DIR, filename)
|
||||
updatevm_firmware_file_path = os.path.join(FWUPD_VM_UPDATES_DIR, filename)
|
||||
|
||||
self._check_domain(updatevm)
|
||||
if os.path.exists(FWUPD_DOM0_UNTRUSTED_DIR):
|
||||
shutil.rmtree(FWUPD_DOM0_UNTRUSTED_DIR)
|
||||
self._create_dirs(FWUPD_DOM0_UPDATES_DIR, FWUPD_DOM0_UNTRUSTED_DIR)
|
||||
|
||||
cmd_copy = 'qvm-run --pass-io %s %s > %s' % (
|
||||
cmd_copy = "qvm-run --pass-io %s %s > %s" % (
|
||||
updatevm,
|
||||
"'cat %s'" % updatevm_firmware_file_path,
|
||||
dom0_firmware_untrusted_path
|
||||
dom0_firmware_untrusted_path,
|
||||
)
|
||||
p = subprocess.Popen(cmd_copy, shell=True)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
raise Exception('qvm-run: Copying firmware file failed!!')
|
||||
raise Exception("qvm-run: Copying firmware file failed!!")
|
||||
|
||||
self._verify_received(
|
||||
FWUPD_DOM0_UNTRUSTED_DIR,
|
||||
fwupd_firmware_file_regex,
|
||||
updatevm
|
||||
FWUPD_DOM0_UNTRUSTED_DIR, fwupd_firmware_file_regex, updatevm
|
||||
)
|
||||
self._check_shasum(dom0_firmware_untrusted_path, sha)
|
||||
untrusted_dir_name = filename.replace(".cab", "")
|
||||
self._extract_archive(
|
||||
dom0_firmware_untrusted_path,
|
||||
FWUPD_DOM0_UNTRUSTED_DIR
|
||||
)
|
||||
signature_name = os.path.join(
|
||||
FWUPD_DOM0_UNTRUSTED_DIR,
|
||||
"firmware*.jcat"
|
||||
)
|
||||
self._extract_archive(dom0_firmware_untrusted_path, FWUPD_DOM0_UNTRUSTED_DIR)
|
||||
signature_name = os.path.join(FWUPD_DOM0_UNTRUSTED_DIR, "firmware*.jcat")
|
||||
file_path = glob.glob(signature_name)
|
||||
if not file_path:
|
||||
raise FileNotFoundError("jcat file not found!")
|
||||
@ -227,10 +183,7 @@ class FwupdReceiveUpdates:
|
||||
untrusted_dir_name = "trusted"
|
||||
verified_file = os.path.join(FWUPD_DOM0_UPDATES_DIR, filename)
|
||||
self.arch_name = "trusted.cab"
|
||||
self.arch_path = os.path.join(
|
||||
FWUPD_DOM0_UPDATES_DIR,
|
||||
self.arch_name
|
||||
)
|
||||
self.arch_path = os.path.join(FWUPD_DOM0_UPDATES_DIR, self.arch_name)
|
||||
shutil.move(verified_file, self.arch_path)
|
||||
else:
|
||||
self.arch_path = os.path.join(FWUPD_DOM0_UPDATES_DIR, filename)
|
||||
@ -245,59 +198,46 @@ class FwupdReceiveUpdates:
|
||||
updatevm -- update VM name
|
||||
"""
|
||||
if metadata_url:
|
||||
metadata_name = metadata_url.replace(
|
||||
FWUPD_DOWNLOAD_PREFIX,
|
||||
""
|
||||
)
|
||||
self.metadata_file = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
metadata_name
|
||||
)
|
||||
self.metadata_file_jcat = self.metadata_file + '.jcat'
|
||||
metadata_name = metadata_url.replace(FWUPD_DOWNLOAD_PREFIX, "")
|
||||
self.metadata_file = os.path.join(FWUPD_DOM0_METADATA_DIR, metadata_name)
|
||||
self.metadata_file_jcat = self.metadata_file + ".jcat"
|
||||
else:
|
||||
self.metadata_file = FWUPD_DOM0_METADATA_FILE
|
||||
self.metadata_file_jcat = FWUPD_DOM0_METADATA_JCAT
|
||||
self.metadata_file_updatevm = self.metadata_file.replace(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
FWUPD_VM_METADATA_DIR
|
||||
FWUPD_DOM0_METADATA_DIR, FWUPD_VM_METADATA_DIR
|
||||
)
|
||||
self.metadata_file_jcat_updatevm = self.metadata_file_jcat.replace(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
FWUPD_VM_METADATA_DIR
|
||||
FWUPD_DOM0_METADATA_DIR, FWUPD_VM_METADATA_DIR
|
||||
)
|
||||
self._check_domain(updatevm)
|
||||
self._create_dirs(FWUPD_DOM0_METADATA_DIR)
|
||||
cmd_file = "'cat %s'" % self.metadata_file_updatevm
|
||||
cmd_jcat = "'cat %s'" % self.metadata_file_jcat_updatevm
|
||||
cmd_copy_metadata_file = 'qvm-run --pass-io %s %s > %s' % (
|
||||
cmd_copy_metadata_file = "qvm-run --pass-io %s %s > %s" % (
|
||||
updatevm,
|
||||
cmd_file,
|
||||
self.metadata_file
|
||||
self.metadata_file,
|
||||
)
|
||||
cmd_copy_metadata_jcat = 'qvm-run --pass-io %s %s > %s' % (
|
||||
cmd_copy_metadata_jcat = "qvm-run --pass-io %s %s > %s" % (
|
||||
updatevm,
|
||||
cmd_jcat,
|
||||
self.metadata_file_jcat
|
||||
self.metadata_file_jcat,
|
||||
)
|
||||
|
||||
p = subprocess.Popen(cmd_copy_metadata_file, shell=True)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
raise Exception('qvm-run: Copying metadata file failed!!')
|
||||
raise Exception("qvm-run: Copying metadata file failed!!")
|
||||
p = subprocess.Popen(cmd_copy_metadata_jcat, shell=True)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
raise Exception('qvm-run": Copying metadata jcat failed!!')
|
||||
|
||||
self._verify_received(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
FWUPD_METADATA_FILES_REGEX,
|
||||
updatevm
|
||||
)
|
||||
self._jcat_verification(
|
||||
self.metadata_file_jcat,
|
||||
FWUPD_DOM0_METADATA_DIR
|
||||
FWUPD_DOM0_METADATA_DIR, FWUPD_METADATA_FILES_REGEX, updatevm
|
||||
)
|
||||
self._jcat_verification(self.metadata_file_jcat, FWUPD_DOM0_METADATA_DIR)
|
||||
os.umask(self.old_umask)
|
||||
|
||||
def clean_cache(self, usbvm=False):
|
||||
|
@ -18,20 +18,13 @@ FWUPDTOOL = "/bin/fwupdtool"
|
||||
BOOT = "/boot"
|
||||
HEADS_UPDATES_DIR = os.path.join(BOOT, "updates")
|
||||
|
||||
EXIT_CODES = {
|
||||
"ERROR": 1,
|
||||
"SUCCESS": 0,
|
||||
"NOTHING_TO_DO": 2,
|
||||
}
|
||||
EXIT_CODES = {"ERROR": 1, "SUCCESS": 0, "NOTHING_TO_DO": 2}
|
||||
|
||||
|
||||
class FwupdHeads:
|
||||
def _get_hwids(self):
|
||||
cmd_hwids = [FWUPDTOOL, "hwids"]
|
||||
p = subprocess.Popen(
|
||||
cmd_hwids,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
p = subprocess.Popen(cmd_hwids, stdout=subprocess.PIPE)
|
||||
self.dom0_hwids_info = p.communicate()[0].decode()
|
||||
if p.returncode != 0:
|
||||
raise Exception("fwudp-qubes: Getting hwids info failed")
|
||||
@ -46,12 +39,8 @@ class FwupdHeads:
|
||||
for line in hwids:
|
||||
if line.startswith("BiosVersion: CBET4000 "):
|
||||
self.heads_version = line.replace(
|
||||
"BiosVersion: CBET4000 ",
|
||||
""
|
||||
).replace(
|
||||
" heads",
|
||||
""
|
||||
)
|
||||
"BiosVersion: CBET4000 ", ""
|
||||
).replace(" heads", "")
|
||||
else:
|
||||
print("Device is not running under the heads firmware!!")
|
||||
print("Exiting...")
|
||||
@ -62,10 +51,7 @@ class FwupdHeads:
|
||||
Parse metadata info.
|
||||
"""
|
||||
cmd_metadata = ["zcat", metadata_file]
|
||||
p = subprocess.Popen(
|
||||
cmd_metadata,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
p = subprocess.Popen(cmd_metadata, stdout=subprocess.PIPE)
|
||||
self.metadata_info = p.communicate()[0].decode()
|
||||
if p.returncode != 0:
|
||||
raise Exception("fwudp-qubes: Parsing metadata failed")
|
||||
@ -90,14 +76,18 @@ class FwupdHeads:
|
||||
return EXIT_CODES["NOTHING_TO_DO"]
|
||||
for release in heads_metadata_info.find("releases").findall("release"):
|
||||
release_ver = release.get("version")
|
||||
if (self.heads_version == "heads" or
|
||||
l_ver(release_ver) > l_ver(self.heads_version)):
|
||||
if (not self.heads_update_version or
|
||||
l_ver(release_ver) > l_ver(self.heads_update_version)):
|
||||
if self.heads_version == "heads" or l_ver(release_ver) > l_ver(
|
||||
self.heads_version
|
||||
):
|
||||
if not self.heads_update_version or l_ver(release_ver) > l_ver(
|
||||
self.heads_update_version
|
||||
):
|
||||
self.heads_update_url = release.find("location").text
|
||||
for sha in release.findall("checksum"):
|
||||
if (".cab" in sha.attrib["filename"]
|
||||
and sha.attrib["type"] == "sha256"):
|
||||
if (
|
||||
".cab" in sha.attrib["filename"]
|
||||
and sha.attrib["type"] == "sha256"
|
||||
):
|
||||
self.heads_update_sha = sha.text
|
||||
self.heads_update_version = release_ver
|
||||
if self.heads_update_url:
|
||||
@ -110,23 +100,14 @@ class FwupdHeads:
|
||||
"""
|
||||
Copies heads update to the boot path
|
||||
"""
|
||||
heads_boot_path = os.path.join(
|
||||
HEADS_UPDATES_DIR,
|
||||
self.heads_update_version
|
||||
)
|
||||
heads_boot_path = os.path.join(HEADS_UPDATES_DIR, self.heads_update_version)
|
||||
update_path = arch_path.replace(".cab", "/firmware.rom")
|
||||
|
||||
heads_update_path = os.path.join(
|
||||
heads_boot_path,
|
||||
"firmware.rom"
|
||||
)
|
||||
heads_update_path = os.path.join(heads_boot_path, "firmware.rom")
|
||||
if not os.path.exists(HEADS_UPDATES_DIR):
|
||||
os.mkdir(HEADS_UPDATES_DIR)
|
||||
if os.path.exists(heads_update_path):
|
||||
print(
|
||||
f"Heads Update == {self.heads_update_version} "
|
||||
"already downloaded."
|
||||
)
|
||||
print(f"Heads Update == {self.heads_update_version} " "already downloaded.")
|
||||
return EXIT_CODES["NOTHING_TO_DO"]
|
||||
else:
|
||||
os.mkdir(heads_boot_path)
|
||||
|
@ -17,10 +17,10 @@ FWUPD_VM_DOWNLOAD = "/usr/libexec/qubes-fwupd/fwupd_download_updates.py"
|
||||
FWUPD_DOM0_UPDATES_DIR = os.path.join(FWUPD_DOM0_DIR, "updates")
|
||||
FWUPD_DOWNLOAD_PREFIX = "https://fwupd.org/downloads/"
|
||||
|
||||
SPECIAL_CHAR_REGEX = re.compile(r'%20|&|\||#')
|
||||
UPDATEVM_REGEX = re.compile(r'^sys-')
|
||||
SPECIAL_CHAR_REGEX = re.compile(r"%20|&|\||#")
|
||||
UPDATEVM_REGEX = re.compile(r"^sys-")
|
||||
|
||||
WARNING_COLOR = '\033[93m'
|
||||
WARNING_COLOR = "\033[93m"
|
||||
|
||||
|
||||
class FwupdUpdate:
|
||||
@ -30,7 +30,7 @@ class FwupdUpdate:
|
||||
Keyword arguments:
|
||||
*args -- paths to be created
|
||||
"""
|
||||
qubes_gid = grp.getgrnam('qubes').gr_gid
|
||||
qubes_gid = grp.getgrnam("qubes").gr_gid
|
||||
self.old_umask = os.umask(0o002)
|
||||
if args is None:
|
||||
raise Exception("Creating directories failed, no paths given.")
|
||||
@ -46,15 +46,8 @@ class FwupdUpdate:
|
||||
)
|
||||
|
||||
def _specify_updatevm(self):
|
||||
cmd_updatevm = [
|
||||
"qubes-prefs",
|
||||
"--force-root",
|
||||
"updatevm",
|
||||
]
|
||||
p = subprocess.Popen(
|
||||
cmd_updatevm,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
cmd_updatevm = ["qubes-prefs", "--force-root", "updatevm"]
|
||||
p = subprocess.Popen(cmd_updatevm, stdout=subprocess.PIPE)
|
||||
self.updatevm = p.communicate()[0].decode().split("\n")[0]
|
||||
if p.returncode != 0 and not UPDATEVM_REGEX.match(self.updatevm):
|
||||
self.updatevm = None
|
||||
@ -62,14 +55,8 @@ class FwupdUpdate:
|
||||
|
||||
def _check_updatevm(self):
|
||||
"""Checks if usbvm is running"""
|
||||
cmd_xl_list = [
|
||||
"xl",
|
||||
"list"
|
||||
]
|
||||
p = subprocess.Popen(
|
||||
cmd_xl_list,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
cmd_xl_list = ["xl", "list"]
|
||||
p = subprocess.Popen(cmd_xl_list, stdout=subprocess.PIPE)
|
||||
output = p.communicate()[0].decode()
|
||||
if p.returncode != 0:
|
||||
raise Exception("fwudp-qubes: Firmware downgrade failed")
|
||||
@ -112,10 +99,10 @@ class FwupdUpdate:
|
||||
"--pass-io",
|
||||
self.updatevm,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
"script --quiet --return --command "
|
||||
f'"{FWUPD_VM_DOWNLOAD} --metadata'
|
||||
f' --url={metadata_url}"'
|
||||
)
|
||||
),
|
||||
]
|
||||
else:
|
||||
cmd_metadata = [
|
||||
@ -123,9 +110,9 @@ class FwupdUpdate:
|
||||
"--pass-io",
|
||||
self.updatevm,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
"script --quiet --return --command "
|
||||
f'"{FWUPD_VM_DOWNLOAD} --metadata"'
|
||||
)
|
||||
),
|
||||
]
|
||||
p = subprocess.Popen(cmd_metadata)
|
||||
p.wait()
|
||||
@ -155,10 +142,10 @@ class FwupdUpdate:
|
||||
"--pass-io",
|
||||
self.updatevm,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
"script --quiet --return --command "
|
||||
f'"{FWUPD_VM_DOWNLOAD} --url={self.enc_url}'
|
||||
f' --sha={sha}"'
|
||||
)
|
||||
),
|
||||
]
|
||||
p = subprocess.Popen(cmd_firmware_download)
|
||||
p.wait()
|
||||
|
@ -32,42 +32,25 @@ try:
|
||||
from fwupd_receive_updates import FwupdReceiveUpdates
|
||||
except ModuleNotFoundError:
|
||||
raise ModuleNotFoundError(
|
||||
"qubes-fwupd modules not found. "
|
||||
"You may need to reinstall package."
|
||||
"qubes-fwupd modules not found. " "You may need to reinstall package."
|
||||
)
|
||||
|
||||
FWUPD_DOM0_DIR = "/root/.cache/fwupd"
|
||||
FWUPD_DOM0_METADATA_DIR = os.path.join(FWUPD_DOM0_DIR, "metadata")
|
||||
FWUPD_DOM0_UPDATES_DIR = os.path.join(FWUPD_DOM0_DIR, "updates")
|
||||
FWUPD_DOM0_METADATA_SIGNATURE = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
"firmware.xml.gz.asc"
|
||||
)
|
||||
FWUPD_DOM0_METADATA_FILE = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
FWUPD_DOM0_METADATA_JCAT = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
"firmware.xml.gz.jcat"
|
||||
FWUPD_DOM0_METADATA_DIR, "firmware.xml.gz.asc"
|
||||
)
|
||||
FWUPD_DOM0_METADATA_FILE = os.path.join(FWUPD_DOM0_METADATA_DIR, "firmware.xml.gz")
|
||||
FWUPD_DOM0_METADATA_JCAT = os.path.join(FWUPD_DOM0_METADATA_DIR, "firmware.xml.gz.jcat")
|
||||
FWUPD_VM_LOG = os.path.join(FWUPD_DOM0_DIR, "usbvm-devices.log")
|
||||
FWUPD_VM_VALIDATE = "/usr/libexec/qubes-fwupd/fwupd_usbvm_validate.py"
|
||||
FWUPD_VM_DIR = "/home/user/.cache/fwupd"
|
||||
FWUPD_VM_UPDATES_DIR = os.path.join(FWUPD_VM_DIR, "updates")
|
||||
FWUPD_VM_METADATA_DIR = os.path.join(FWUPD_VM_DIR, "metadata")
|
||||
FWUPD_VM_METADATA_SIGNATURE = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz.asc"
|
||||
)
|
||||
FWUPD_VM_METADATA_FILE = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
FWUPD_VM_METADATA_JCAT = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz.jcat"
|
||||
)
|
||||
FWUPD_VM_METADATA_SIGNATURE = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz.asc")
|
||||
FWUPD_VM_METADATA_FILE = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz")
|
||||
FWUPD_VM_METADATA_JCAT = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz.jcat")
|
||||
FWUPD_DOWNLOAD_PREFIX = "https://fwupd.org/downloads/"
|
||||
|
||||
FWUPDMGR = "/bin/fwupdmgr"
|
||||
@ -78,11 +61,9 @@ USBVM_N = "sys-usb"
|
||||
BIOS_UPDATE_FLAG = os.path.join(FWUPD_DOM0_DIR, "bios_update")
|
||||
LVFS_TESTING_DOM0_FLAG = os.path.join(FWUPD_DOM0_DIR, "lvfs_testing")
|
||||
LVFS_TESTING_USBVM_FLAG = os.path.join(FWUPD_VM_DIR, "lvfs_testing")
|
||||
METADATA_REFRESH_REGEX = re.compile(
|
||||
r"^Successfully refreshed metadata manually$"
|
||||
)
|
||||
METADATA_REFRESH_REGEX = re.compile(r"^Successfully refreshed metadata manually$")
|
||||
|
||||
SPECIAL_CHAR_REGEX = re.compile(r'%20|&|\||#')
|
||||
SPECIAL_CHAR_REGEX = re.compile(r"%20|&|\||#")
|
||||
|
||||
|
||||
HELP = {
|
||||
@ -100,28 +81,20 @@ HELP = {
|
||||
"update": "Update chosen device to latest firmware version",
|
||||
"update-heads": "Updates heads firmware to the latest version",
|
||||
"downgrade": "Downgrade chosen device to chosen firmware version",
|
||||
"clean": "Delete all cached update files\n"
|
||||
"clean": "Delete all cached update files\n",
|
||||
}
|
||||
],
|
||||
"Flags": [
|
||||
{
|
||||
"--whonix": "Download firmware updates via Tor",
|
||||
"--device": "Specify device for heads update (default - x230)",
|
||||
"--url": "Address of the custom metadata remote server\n"
|
||||
}
|
||||
],
|
||||
"Help": [
|
||||
{
|
||||
"-h --help": "Show help options\n"
|
||||
"--url": "Address of the custom metadata remote server\n",
|
||||
}
|
||||
],
|
||||
"Help": [{"-h --help": "Show help options\n"}],
|
||||
}
|
||||
|
||||
EXIT_CODES = {
|
||||
"ERROR": 1,
|
||||
"SUCCESS": 0,
|
||||
"NOTHING_TO_DO": 2,
|
||||
}
|
||||
EXIT_CODES = {"ERROR": 1, "SUCCESS": 0, "NOTHING_TO_DO": 2}
|
||||
|
||||
|
||||
class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
@ -143,7 +116,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
f'script --quiet --return --command "{FWUPD_VM_VALIDATE} dirs"'
|
||||
f'script --quiet --return --command "{FWUPD_VM_VALIDATE} dirs"',
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_dirs)
|
||||
p.wait()
|
||||
@ -158,7 +131,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
f'script --quiet --return --command "{arch_validate}"'
|
||||
f'script --quiet --return --command "{arch_validate}"',
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_arch)
|
||||
p.wait()
|
||||
@ -168,18 +141,17 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
def _copy_usbvm_metadata(self):
|
||||
"""Copies metadata files to usbvm."""
|
||||
self.metadata_file_usbvm = self.metadata_file.replace(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
FWUPD_VM_METADATA_DIR
|
||||
FWUPD_DOM0_METADATA_DIR, FWUPD_VM_METADATA_DIR
|
||||
)
|
||||
self.metadata_file_jcat_usbvm = self.metadata_file_usbvm + ".jcat"
|
||||
cat_file = f"cat > {self.metadata_file_usbvm}"
|
||||
cmd_copy_file = (
|
||||
f'cat {self.metadata_file} | '
|
||||
f"cat {self.metadata_file} | "
|
||||
f'qvm-run --nogui --pass-io {USBVM_N} "{cat_file}"'
|
||||
)
|
||||
cat_jcat = f"cat > {self.metadata_file_jcat_usbvm}"
|
||||
cmd_copy_jcat = (
|
||||
f'cat {self.metadata_file_jcat} | '
|
||||
f"cat {self.metadata_file_jcat} | "
|
||||
f'qvm-run --nogui --pass-io {USBVM_N} "{cat_jcat}"'
|
||||
)
|
||||
p = subprocess.Popen(cmd_copy_file, shell=True)
|
||||
@ -195,15 +167,12 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"""Checks GPG signature of metadata files in usbvm."""
|
||||
usbvm_cmd = f'"{FWUPD_VM_VALIDATE} metadata"'
|
||||
if metadata_url:
|
||||
usbvm_cmd = (
|
||||
f'"{FWUPD_VM_VALIDATE} metadata --url={metadata_url}"'
|
||||
)
|
||||
usbvm_cmd = f'"{FWUPD_VM_VALIDATE} metadata --url={metadata_url}"'
|
||||
cmd_validate_metadata = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
'script --quiet --return --command'
|
||||
f' {usbvm_cmd}'
|
||||
"script --quiet --return --command" f" {usbvm_cmd}",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_metadata)
|
||||
p.wait()
|
||||
@ -218,10 +187,10 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
"script --quiet --return --command "
|
||||
f'"{FWUPDMGR} refresh {self.metadata_file_usbvm} '
|
||||
f'{sig_metadata_file} {self.lvfs}"'
|
||||
)
|
||||
),
|
||||
]
|
||||
p = subprocess.Popen(cmd_refresh_metadata)
|
||||
p.wait()
|
||||
@ -238,8 +207,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
output_path = os.path.join(FWUPD_VM_UPDATES_DIR, arch_name)
|
||||
cat_file = f"cat > {output_path}"
|
||||
cmd_copy_file = (
|
||||
f'cat {arch_path} | '
|
||||
f'qvm-run --nogui --pass-io {USBVM_N} "{cat_file}"'
|
||||
f"cat {arch_path} | " f'qvm-run --nogui --pass-io {USBVM_N} "{cat_file}"'
|
||||
)
|
||||
p = subprocess.Popen(cmd_copy_file, shell=True)
|
||||
p.wait()
|
||||
@ -257,8 +225,8 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
f'script --quiet --return --command'
|
||||
f' "{FWUPDMGR} install {arch_path}" /dev/null'
|
||||
f"script --quiet --return --command"
|
||||
f' "{FWUPDMGR} install {arch_path}" /dev/null',
|
||||
]
|
||||
p = subprocess.Popen(CMD_update)
|
||||
p.wait()
|
||||
@ -276,8 +244,8 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
f'script --quiet --return --command'
|
||||
f' "{FWUPDMGR} --allow-older install {arch_path}" /dev/null'
|
||||
f"script --quiet --return --command"
|
||||
f' "{FWUPDMGR} --allow-older install {arch_path}" /dev/null',
|
||||
]
|
||||
p = subprocess.Popen(CMD_downgrade)
|
||||
p.wait()
|
||||
@ -290,7 +258,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
f'script --quiet --return --command "{FWUPD_VM_VALIDATE} clean"'
|
||||
f'script --quiet --return --command "{FWUPD_VM_VALIDATE} clean"',
|
||||
]
|
||||
p = subprocess.Popen(cmd_clean)
|
||||
p.wait()
|
||||
@ -299,12 +267,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
|
||||
def _enable_lvfs_testing_dom0(self):
|
||||
"""Checks and enable lvfs-testing for custom metadata in dom0"""
|
||||
cmd_lvfs_testing = [
|
||||
FWUPDMGR,
|
||||
"enable-remote",
|
||||
"-y",
|
||||
"lvfs-testing"
|
||||
]
|
||||
cmd_lvfs_testing = [FWUPDMGR, "enable-remote", "-y", "lvfs-testing"]
|
||||
if not os.path.exists(LVFS_TESTING_DOM0_FLAG):
|
||||
p = subprocess.Popen(cmd_lvfs_testing)
|
||||
p.wait()
|
||||
@ -321,27 +284,24 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
"script --quiet --return --command "
|
||||
f'"{FWUPDMGR} enable-remote -y lvfs-testing"'
|
||||
)
|
||||
),
|
||||
]
|
||||
cmd_validate_flag = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
"script --quiet --return --command "
|
||||
f'"ls {LVFS_TESTING_USBVM_FLAG} &>/dev/null"'
|
||||
)
|
||||
),
|
||||
]
|
||||
cmd_touch_flag = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
f'"touch {LVFS_TESTING_USBVM_FLAG}"'
|
||||
)
|
||||
("script --quiet --return --command " f'"touch {LVFS_TESTING_USBVM_FLAG}"'),
|
||||
]
|
||||
flag = subprocess.Popen(cmd_validate_flag)
|
||||
flag.wait()
|
||||
@ -365,11 +325,8 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"""
|
||||
if metadata_url:
|
||||
metadata_name = metadata_url.replace(FWUPD_DOWNLOAD_PREFIX, "")
|
||||
self.metadata_file = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
metadata_name
|
||||
)
|
||||
self.metadata_file_jcat = self.metadata_file + '.jcat'
|
||||
self.metadata_file = os.path.join(FWUPD_DOM0_METADATA_DIR, metadata_name)
|
||||
self.metadata_file_jcat = self.metadata_file + ".jcat"
|
||||
self.lvfs = "lvfs-testing"
|
||||
self._enable_lvfs_testing_dom0()
|
||||
self._enable_lvfs_testing_usbvm(usbvm=usbvm)
|
||||
@ -388,12 +345,9 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"refresh",
|
||||
self.metadata_file,
|
||||
self.metadata_file_jcat,
|
||||
self.lvfs
|
||||
self.lvfs,
|
||||
]
|
||||
p = subprocess.Popen(
|
||||
cmd_refresh,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
p = subprocess.Popen(cmd_refresh, stdout=subprocess.PIPE)
|
||||
self.output = p.communicate()[0].decode()
|
||||
print(self.output)
|
||||
if p.returncode != 0:
|
||||
@ -403,14 +357,8 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
|
||||
def _get_dom0_updates(self):
|
||||
"""Gathers infromations about available updates."""
|
||||
cmd_get_dom0_updates = [
|
||||
FWUPDAGENT,
|
||||
"get-updates"
|
||||
]
|
||||
p = subprocess.Popen(
|
||||
cmd_get_dom0_updates,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
cmd_get_dom0_updates = [FWUPDAGENT, "get-updates"]
|
||||
p = subprocess.Popen(cmd_get_dom0_updates, stdout=subprocess.PIPE)
|
||||
self.dom0_updates_info = p.communicate()[0].decode()
|
||||
if p.returncode != 0 and p.returncode != 2:
|
||||
raise Exception("fwudp-qubes: Getting available updates failed")
|
||||
@ -424,17 +372,19 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
self.dom0_updates_info_dict = json.loads(updates_info)
|
||||
self.dom0_updates_list = [
|
||||
{
|
||||
"Name": device["Name"],
|
||||
"Version": device["Version"],
|
||||
"Releases": [
|
||||
{
|
||||
"Version": update["Version"],
|
||||
"Url": update["Uri"],
|
||||
"Checksum": update["Checksum"][-1],
|
||||
"Description": update["Description"]
|
||||
} for update in device["Releases"]
|
||||
]
|
||||
} for device in self.dom0_updates_info_dict["Devices"]
|
||||
"Name": device["Name"],
|
||||
"Version": device["Version"],
|
||||
"Releases": [
|
||||
{
|
||||
"Version": update["Version"],
|
||||
"Url": update["Uri"],
|
||||
"Checksum": update["Checksum"][-1],
|
||||
"Description": update["Description"],
|
||||
}
|
||||
for update in device["Releases"]
|
||||
],
|
||||
}
|
||||
for device in self.dom0_updates_info_dict["Devices"]
|
||||
]
|
||||
|
||||
def _download_firmware_updates(self, url, sha, whonix=False):
|
||||
@ -476,22 +426,20 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
self._updates_crawler(updates_dict["dom0"])
|
||||
if usbvm:
|
||||
self._updates_crawler(
|
||||
updates_dict["usbvm"],
|
||||
usbvm=True,
|
||||
prefix=dom0_updates_num
|
||||
updates_dict["usbvm"], usbvm=True, prefix=dom0_updates_num
|
||||
)
|
||||
|
||||
while True:
|
||||
try:
|
||||
print("If you want to abandon process press 'N'.")
|
||||
choice = input("Otherwise choose a device number: ")
|
||||
if choice == 'N' or choice == 'n':
|
||||
if choice == "N" or choice == "n":
|
||||
return EXIT_CODES["NOTHING_TO_DO"]
|
||||
device_num = int(choice)-1
|
||||
device_num = int(choice) - 1
|
||||
if 0 <= device_num < len(updates_list):
|
||||
if not downgrade:
|
||||
if device_num >= dom0_updates_num:
|
||||
return "usbvm", device_num-dom0_updates_num
|
||||
return "usbvm", device_num - dom0_updates_num
|
||||
else:
|
||||
return "dom0", device_num
|
||||
break
|
||||
@ -519,9 +467,9 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
print(f" Description:{description}")
|
||||
print("If you want to abandon downgrade process press N.")
|
||||
choice = input("Otherwise choose downgrade number: ")
|
||||
if choice == 'N' or choice == 'n':
|
||||
if choice == "N" or choice == "n":
|
||||
return EXIT_CODES["NOTHING_TO_DO"]
|
||||
downgrade_num = int(choice)-1
|
||||
downgrade_num = int(choice) - 1
|
||||
if 0 <= downgrade_num < len(releases):
|
||||
if device_num >= dom0_updates_num:
|
||||
device_abs_num = device_num - dom0_updates_num
|
||||
@ -555,11 +503,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
Keywords arguments:
|
||||
arch_path - absolute path to firmware update archive
|
||||
"""
|
||||
cmd_install = [
|
||||
FWUPDMGR,
|
||||
"install",
|
||||
arch_path
|
||||
]
|
||||
cmd_install = [FWUPDMGR, "install", arch_path]
|
||||
p = subprocess.Popen(cmd_install)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
@ -567,19 +511,11 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
|
||||
def _read_dmi(self):
|
||||
"""Reads BIOS information from DMI."""
|
||||
cmd_dmidecode_version = [
|
||||
"dmidecode",
|
||||
"-s",
|
||||
"bios-version"
|
||||
]
|
||||
cmd_dmidecode_version = ["dmidecode", "-s", "bios-version"]
|
||||
p = subprocess.Popen(cmd_dmidecode_version, stdout=subprocess.PIPE)
|
||||
p.wait()
|
||||
self.dmi_version = p.communicate()[0].decode()
|
||||
cmd_dmidecode = [
|
||||
"dmidecode",
|
||||
"-t",
|
||||
"bios"
|
||||
]
|
||||
cmd_dmidecode = ["dmidecode", "-t", "bios"]
|
||||
p = subprocess.Popen(cmd_dmidecode, stdout=subprocess.PIPE)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
@ -604,20 +540,12 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
if vendor not in dmi_info:
|
||||
raise ValueError("Wrong firmware provider.")
|
||||
if not downgrade and l_ver(version) <= l_ver(self.dmi_version):
|
||||
raise ValueError(
|
||||
f"{version} < {self.dmi_version} Downgrade not allowed"
|
||||
)
|
||||
raise ValueError(f"{version} < {self.dmi_version} Downgrade not allowed")
|
||||
|
||||
def _get_dom0_devices(self):
|
||||
"""Gathers information about devices connected in dom0."""
|
||||
cmd_get_dom0_devices = [
|
||||
FWUPDAGENT,
|
||||
"get-devices"
|
||||
]
|
||||
p = subprocess.Popen(
|
||||
cmd_get_dom0_devices,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
cmd_get_dom0_devices = [FWUPDAGENT, "get-devices"]
|
||||
p = subprocess.Popen(cmd_get_dom0_devices, stdout=subprocess.PIPE)
|
||||
self.dom0_devices_info = p.communicate()[0].decode()
|
||||
if p.returncode != 0:
|
||||
raise Exception("fwudp-qubes: Getting devices info failed")
|
||||
@ -629,15 +557,11 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
usbvm_cmd = f'"{FWUPDAGENT} get-devices"'
|
||||
log_file = f" > {FWUPD_VM_LOG}"
|
||||
cmd_get_usbvm_devices = (
|
||||
f'qvm-run --nogui --pass-io {USBVM_N} {usbvm_cmd}{log_file}'
|
||||
)
|
||||
p = subprocess.Popen(
|
||||
cmd_get_usbvm_devices,
|
||||
shell=True
|
||||
f"qvm-run --nogui --pass-io {USBVM_N} {usbvm_cmd}{log_file}"
|
||||
)
|
||||
p = subprocess.Popen(cmd_get_usbvm_devices, shell=True)
|
||||
p.wait()
|
||||
if (p.returncode != 0 and p.returncode != 2
|
||||
and not os.path.exists(FWUPD_VM_LOG)):
|
||||
if p.returncode != 0 and p.returncode != 2 and not os.path.exists(FWUPD_VM_LOG):
|
||||
raise Exception("fwudp-qubes: Getting usbvm devices info failed")
|
||||
if not os.path.exists(FWUPD_VM_LOG):
|
||||
raise Exception("usbvm device info log does not exist")
|
||||
@ -658,7 +582,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
{
|
||||
"Name": device["Name"],
|
||||
"Version": device["Version"],
|
||||
"Releases": []
|
||||
"Releases": [],
|
||||
}
|
||||
)
|
||||
current_version = device["Version"]
|
||||
@ -669,7 +593,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"Version": update["Version"],
|
||||
"Url": update["Uri"],
|
||||
"Checksum": update["Checksum"][-1],
|
||||
"Description": update["Description"]
|
||||
"Description": update["Description"],
|
||||
}
|
||||
)
|
||||
if not self.usbvm_updates_list[-1]["Releases"]:
|
||||
@ -691,13 +615,11 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
self._parse_usbvm_updates(raw)
|
||||
update_dict = {
|
||||
"usbvm": self.usbvm_updates_list,
|
||||
"dom0": self.dom0_updates_list
|
||||
"dom0": self.dom0_updates_list,
|
||||
}
|
||||
ret_input = self._user_input(update_dict, usbvm=True)
|
||||
else:
|
||||
update_dict = {
|
||||
"dom0": self.dom0_updates_list
|
||||
}
|
||||
update_dict = {"dom0": self.dom0_updates_list}
|
||||
ret_input = self._user_input(update_dict)
|
||||
if ret_input == EXIT_CODES["NOTHING_TO_DO"]:
|
||||
exit(EXIT_CODES["NOTHING_TO_DO"])
|
||||
@ -741,10 +663,11 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"Version": downgrade["Version"],
|
||||
"Description": downgrade["Description"],
|
||||
"Url": downgrade["Uri"],
|
||||
"Checksum": downgrade["Checksum"][-1]
|
||||
} for downgrade in device["Releases"]
|
||||
"Checksum": downgrade["Checksum"][-1],
|
||||
}
|
||||
for downgrade in device["Releases"]
|
||||
if l_ver(downgrade["Version"]) < l_ver(version)
|
||||
]
|
||||
],
|
||||
}
|
||||
)
|
||||
return downgrades
|
||||
@ -755,12 +678,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
Keywords arguments:
|
||||
arch_path - absolute path to firmware downgrade archive
|
||||
"""
|
||||
cmd_install = [
|
||||
FWUPDMGR,
|
||||
"--allow-older",
|
||||
"install",
|
||||
arch_path
|
||||
]
|
||||
cmd_install = [FWUPDMGR, "--allow-older", "install", arch_path]
|
||||
p = subprocess.Popen(cmd_install)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
@ -780,19 +698,10 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
with open(FWUPD_VM_LOG) as usbvm_device_info:
|
||||
raw = usbvm_device_info.read()
|
||||
usbvm_downgrades = self._parse_downgrades(raw)
|
||||
downgrade_dict = {
|
||||
"usbvm": usbvm_downgrades,
|
||||
"dom0": dom0_downgrades
|
||||
}
|
||||
ret_input = self._user_input(
|
||||
downgrade_dict,
|
||||
downgrade=True,
|
||||
usbvm=True
|
||||
)
|
||||
downgrade_dict = {"usbvm": usbvm_downgrades, "dom0": dom0_downgrades}
|
||||
ret_input = self._user_input(downgrade_dict, downgrade=True, usbvm=True)
|
||||
else:
|
||||
downgrade_dict = {
|
||||
"dom0": dom0_downgrades
|
||||
}
|
||||
downgrade_dict = {"dom0": dom0_downgrades}
|
||||
ret_input = self._user_input(downgrade_dict, downgrade=True)
|
||||
if ret_input == EXIT_CODES["NOTHING_TO_DO"]:
|
||||
exit(EXIT_CODES["NOTHING_TO_DO"])
|
||||
@ -800,18 +709,14 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
releases = downgrade_dict[vm_name][device_choice]["Releases"]
|
||||
downgrade_url = releases[downgrade_choice]["Url"]
|
||||
downgrade_sha = releases[downgrade_choice]["Checksum"]
|
||||
self._download_firmware_updates(
|
||||
downgrade_url,
|
||||
downgrade_sha,
|
||||
whonix=whonix
|
||||
)
|
||||
self._download_firmware_updates(downgrade_url, downgrade_sha, whonix=whonix)
|
||||
if downgrade_dict[vm_name][device_choice]["Name"] == "System Firmware":
|
||||
Path(BIOS_UPDATE_FLAG).touch(mode=0o644, exist_ok=True)
|
||||
extracted_path = self.arch_path.replace(".cab", "")
|
||||
self._verify_dmi(
|
||||
extracted_path,
|
||||
downgrade_dict[vm_name][device_choice]["Version"],
|
||||
downgrade=True
|
||||
downgrade=True,
|
||||
)
|
||||
if vm_name == "dom0":
|
||||
self._install_dom0_firmware_downgrade(self.arch_path)
|
||||
@ -828,13 +733,14 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
updev_dict -- update/device information dictionary
|
||||
level -- level of the tree
|
||||
"""
|
||||
|
||||
def _tabs(key_word):
|
||||
return key_word + '\t'*(4 - int(len(key_word)/8))
|
||||
return key_word + "\t" * (4 - int(len(key_word) / 8))
|
||||
|
||||
decorator = "==================================="
|
||||
print(2*decorator)
|
||||
print(2 * decorator)
|
||||
for updev_key in updev_dict:
|
||||
style = '\t'*level
|
||||
style = "\t" * level
|
||||
output = style + _tabs(updev_key + ":")
|
||||
if len(updev_key) > 12:
|
||||
continue
|
||||
@ -844,7 +750,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
continue
|
||||
if updev_key == "Name":
|
||||
print(style + updev_dict["Name"])
|
||||
print(2*decorator)
|
||||
print(2 * decorator)
|
||||
continue
|
||||
if isinstance(updev_dict[updev_key], str):
|
||||
print(output + updev_dict[updev_key])
|
||||
@ -853,9 +759,9 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
elif isinstance(updev_dict[updev_key][0], str):
|
||||
for i, data in enumerate(updev_dict[updev_key]):
|
||||
if i == 0:
|
||||
print(output + u'\u00B7' + data)
|
||||
print(output + "\u00B7" + data)
|
||||
continue
|
||||
print(style + _tabs(' ') + u'\u00B7' + data)
|
||||
print(style + _tabs(" ") + "\u00B7" + data)
|
||||
elif isinstance(updev_dict[updev_key][0], dict):
|
||||
if level == 0 and help_f is True:
|
||||
print(output)
|
||||
@ -866,7 +772,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
print(f"{USBVM_N} {output}")
|
||||
|
||||
for nested_dict in updev_dict[updev_key]:
|
||||
self._output_crawler(nested_dict, level+1)
|
||||
self._output_crawler(nested_dict, level + 1)
|
||||
|
||||
def _updates_crawler(self, updates_list, usbvm=False, prefix=0):
|
||||
"""Prints updates information for dom0 and usbvm
|
||||
@ -899,10 +805,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
print(f" Current firmware version:\t {device['Version']}")
|
||||
for update in device["Releases"]:
|
||||
print(decorator)
|
||||
print(
|
||||
" Firmware update "
|
||||
f"version:\t {update['Version']}"
|
||||
)
|
||||
print(" Firmware update " f"version:\t {update['Version']}")
|
||||
print(f" URL:\t {update['Url']}")
|
||||
print(f" SHA256 checksum:\t {update['Checksum']}")
|
||||
description = update["Description"].replace("<p>", "")
|
||||
@ -960,14 +863,8 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
|
||||
def check_usbvm(self):
|
||||
"""Checks if usbvm is running"""
|
||||
cmd_xl_list = [
|
||||
"xl",
|
||||
"list"
|
||||
]
|
||||
p = subprocess.Popen(
|
||||
cmd_xl_list,
|
||||
stdout=subprocess.PIPE
|
||||
)
|
||||
cmd_xl_list = ["xl", "list"]
|
||||
p = subprocess.Popen(cmd_xl_list, stdout=subprocess.PIPE)
|
||||
self.output = p.communicate()[0].decode()
|
||||
if p.returncode != 0:
|
||||
raise Exception("fwudp-qubes: Firmware downgrade failed")
|
||||
@ -1011,13 +908,9 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
"""
|
||||
self._check_fwupdtool_version()
|
||||
if metadata_url:
|
||||
custom_metadata_name = metadata_url.replace(
|
||||
FWUPD_DOWNLOAD_PREFIX,
|
||||
""
|
||||
)
|
||||
custom_metadata_name = metadata_url.replace(FWUPD_DOWNLOAD_PREFIX, "")
|
||||
self.metadata_file = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
custom_metadata_name
|
||||
FWUPD_DOM0_METADATA_DIR, custom_metadata_name
|
||||
)
|
||||
else:
|
||||
self.metadata_file = FWUPD_DOM0_METADATA_FILE
|
||||
@ -1028,10 +921,7 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
return EXIT_CODES["NOTHING_TO_DO"]
|
||||
if self._parse_heads_updates(device) == EXIT_CODES["NOTHING_TO_DO"]:
|
||||
return EXIT_CODES["NOTHING_TO_DO"]
|
||||
self._download_firmware_updates(
|
||||
self.heads_update_url,
|
||||
self.heads_update_sha
|
||||
)
|
||||
self._download_firmware_updates(self.heads_update_url, self.heads_update_sha)
|
||||
return_code = self._copy_heads_firmware(self.arch_path)
|
||||
if return_code == EXIT_CODES["NOTHING_TO_DO"]:
|
||||
exit(EXIT_CODES["NOTHING_TO_DO"])
|
||||
@ -1041,9 +931,9 @@ class QubesFwupdmgr(FwupdHeads, FwupdUpdate, FwupdReceiveUpdates):
|
||||
try:
|
||||
print("An update requires a reboot to complete.")
|
||||
choice = input("Do you want to restart now? (Y|N)\n")
|
||||
if choice == 'N' or choice == 'n':
|
||||
if choice == "N" or choice == "n":
|
||||
return EXIT_CODES["SUCCESS"]
|
||||
elif choice == 'Y' or choice == 'y':
|
||||
elif choice == "Y" or choice == "y":
|
||||
print("Rebooting...")
|
||||
os.system("reboot")
|
||||
else:
|
||||
@ -1117,11 +1007,7 @@ def main():
|
||||
elif sys.argv[1] == "refresh" and "--whonix" not in sys.argv:
|
||||
q.refresh_metadata(usbvm=sys_usb, metadata_url=metadata_url)
|
||||
elif sys.argv[1] == "refresh" and "--whonix" in sys.argv:
|
||||
q.refresh_metadata(
|
||||
usbvm=sys_usb,
|
||||
whonix=True,
|
||||
metadata_url=metadata_url
|
||||
)
|
||||
q.refresh_metadata(usbvm=sys_usb, whonix=True, metadata_url=metadata_url)
|
||||
elif sys.argv[1] == "update-heads" and "--whonix" not in sys.argv:
|
||||
q.heads_update(device=device, metadata_url=metadata_url)
|
||||
elif sys.argv[1] == "update-heads" and "--whonix" in sys.argv:
|
||||
@ -1131,5 +1017,5 @@ def main():
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -16,7 +16,7 @@ import subprocess
|
||||
FWUPD_VM_DIR = "/home/user/.cache/fwupd"
|
||||
FWUPD_VM_UPDATES_DIR = os.path.join(FWUPD_VM_DIR, "updates")
|
||||
FWUPD_VM_METADATA_DIR = os.path.join(FWUPD_VM_DIR, "metadata")
|
||||
WARNING_COLOR = '\033[93m'
|
||||
WARNING_COLOR = "\033[93m"
|
||||
FWUPD_PKI = "/etc/pki/fwupd"
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ class FwupdVmCommon:
|
||||
Keyword arguments:
|
||||
*args -- paths to be created
|
||||
"""
|
||||
qubes_gid = grp.getgrnam('qubes').gr_gid
|
||||
qubes_gid = grp.getgrnam("qubes").gr_gid
|
||||
self.old_umask = os.umask(0o002)
|
||||
if args is None:
|
||||
raise Exception("Creating directories failed, no paths given.")
|
||||
@ -49,14 +49,11 @@ class FwupdVmCommon:
|
||||
file_path -- absolute path to the file
|
||||
sha -- SHA256 checksum of the file
|
||||
"""
|
||||
with open(file_path, 'rb') as f:
|
||||
with open(file_path, "rb") as f:
|
||||
c_sha = hashlib.sha256(f.read()).hexdigest()
|
||||
if c_sha != sha:
|
||||
self.clean_vm_cache()
|
||||
raise ValueError(
|
||||
"Computed checksum %s did NOT match %s. " %
|
||||
(c_sha, sha)
|
||||
)
|
||||
raise ValueError("Computed checksum %s did NOT match %s. " % (c_sha, sha))
|
||||
|
||||
def validate_vm_dirs(self):
|
||||
"""Validates and creates directories"""
|
||||
@ -80,25 +77,16 @@ class FwupdVmCommon:
|
||||
file_path -- absolute path to jcat file
|
||||
file_directory -- absolute path to the directory to jcat file location
|
||||
"""
|
||||
cmd_jcat = [
|
||||
"jcat-tool",
|
||||
"verify",
|
||||
f"{file_path}",
|
||||
"--public-keys",
|
||||
FWUPD_PKI
|
||||
]
|
||||
cmd_jcat = ["jcat-tool", "verify", f"{file_path}", "--public-keys", FWUPD_PKI]
|
||||
p = subprocess.Popen(
|
||||
cmd_jcat,
|
||||
cwd=file_directory,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE
|
||||
cmd_jcat, cwd=file_directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
stdout, __ = p.communicate()
|
||||
verification = stdout.decode('utf-8')
|
||||
verification = stdout.decode("utf-8")
|
||||
print(verification)
|
||||
if p.returncode != 0:
|
||||
self.clean_vm_cache()
|
||||
raise Exception('jcat-tool: Verification failed')
|
||||
raise Exception("jcat-tool: Verification failed")
|
||||
|
||||
def clean_vm_cache(self):
|
||||
"""Removes updates data"""
|
||||
|
@ -41,12 +41,7 @@ class DownloadData(FwupdVmCommon):
|
||||
metadata_url = METADATA_URL
|
||||
else:
|
||||
metadata_url = self.custom_url
|
||||
cmd_metadata = [
|
||||
"wget",
|
||||
"-P",
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
metadata_url
|
||||
]
|
||||
cmd_metadata = ["wget", "-P", FWUPD_VM_METADATA_DIR, metadata_url]
|
||||
p = subprocess.Popen(cmd_metadata)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
@ -62,12 +57,7 @@ class DownloadData(FwupdVmCommon):
|
||||
metadata_url = METADATA_URL
|
||||
else:
|
||||
metadata_url = self.custom_url
|
||||
cmd_metadata = [
|
||||
"wget",
|
||||
"-P",
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
f"{metadata_url}.jcat"
|
||||
]
|
||||
cmd_metadata = ["wget", "-P", FWUPD_VM_METADATA_DIR, f"{metadata_url}.jcat"]
|
||||
p = subprocess.Popen(cmd_metadata)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
@ -81,20 +71,13 @@ class DownloadData(FwupdVmCommon):
|
||||
"""Downloads default metadata and its signatures"""
|
||||
if url is not None:
|
||||
self.custom_url = url
|
||||
custom_metadata_name = url.replace(
|
||||
FWUPD_DOWNLOAD_PREFIX,
|
||||
""
|
||||
)
|
||||
custom_metadata_name = url.replace(FWUPD_DOWNLOAD_PREFIX, "")
|
||||
self.metadata_file = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
custom_metadata_name
|
||||
FWUPD_VM_METADATA_DIR, custom_metadata_name
|
||||
)
|
||||
else:
|
||||
self.custom_url = None
|
||||
self.metadata_file = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
self.metadata_file = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz")
|
||||
self.validate_vm_dirs()
|
||||
self._download_metadata_file()
|
||||
self._download_metadata_jcat()
|
||||
@ -110,12 +93,7 @@ class DownloadData(FwupdVmCommon):
|
||||
self.arch_name = url.replace("https://fwupd.org/downloads/", "")
|
||||
self._decrypt_update_url(url)
|
||||
update_path = os.path.join(FWUPD_VM_UPDATES_DIR, self.arch_name)
|
||||
cmd_update = [
|
||||
"wget",
|
||||
"-O",
|
||||
update_path,
|
||||
self.dec_url
|
||||
]
|
||||
cmd_update = ["wget", "-O", update_path, self.dec_url]
|
||||
p = subprocess.Popen(cmd_update)
|
||||
p.wait()
|
||||
if p.returncode != 0:
|
||||
@ -145,5 +123,5 @@ def main():
|
||||
raise Exception("Invalid command!!!")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -18,14 +18,8 @@ from fwupd_common_vm import FwupdVmCommon
|
||||
FWUPD_VM_DIR = "/home/user/.cache/fwupd"
|
||||
FWUPD_VM_UPDATES_DIR = os.path.join(FWUPD_VM_DIR, "updates")
|
||||
FWUPD_VM_METADATA_DIR = os.path.join(FWUPD_VM_DIR, "metadata")
|
||||
FWUPD_VM_METADATA_JCAT = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz.jcat"
|
||||
)
|
||||
FWUPD_VM_METADATA_FILE = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
FWUPD_VM_METADATA_JCAT = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz.jcat")
|
||||
FWUPD_VM_METADATA_FILE = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz")
|
||||
FWUPDMGR = "/bin/fwupdmgr"
|
||||
FWUPD_DOWNLOAD_PREFIX = "https://fwupd.org/downloads/"
|
||||
|
||||
@ -41,18 +35,14 @@ class FwupdUsbvmUpdates(FwupdVmCommon):
|
||||
"""
|
||||
for untrusted_f in os.listdir(files_path):
|
||||
if not regex_pattern.match(untrusted_f):
|
||||
raise Exception(
|
||||
'Dom0 sent unexpected file'
|
||||
)
|
||||
raise Exception("Dom0 sent unexpected file")
|
||||
f = untrusted_f
|
||||
assert '/' not in f
|
||||
assert '\0' not in f
|
||||
assert '\x1b' not in f
|
||||
assert "/" not in f
|
||||
assert "\0" not in f
|
||||
assert "\x1b" not in f
|
||||
path_f = os.path.join(files_path, f)
|
||||
if os.path.islink(path_f) or not os.path.isfile(path_f):
|
||||
raise Exception(
|
||||
'Dom0 sent not regular file'
|
||||
)
|
||||
raise Exception("Dom0 sent not regular file")
|
||||
|
||||
def _extract_archive(self, archive_path, output_path):
|
||||
"""Extracts archive file to the specified directory.
|
||||
@ -61,39 +51,22 @@ class FwupdUsbvmUpdates(FwupdVmCommon):
|
||||
archive_path -- absolute path to archive file
|
||||
output_path -- absolute path to the output directory
|
||||
"""
|
||||
cmd_extract = [
|
||||
"gcab",
|
||||
"-x",
|
||||
f"--directory={output_path}",
|
||||
f"{archive_path}"
|
||||
]
|
||||
cmd_extract = ["gcab", "-x", f"--directory={output_path}", f"{archive_path}"]
|
||||
p = subprocess.Popen(cmd_extract, stdout=subprocess.PIPE)
|
||||
p.communicate()[0].decode('ascii')
|
||||
p.communicate()[0].decode("ascii")
|
||||
if p.returncode != 0:
|
||||
raise Exception(
|
||||
'gcab: Error while extracting %s.' %
|
||||
archive_path
|
||||
)
|
||||
raise Exception("gcab: Error while extracting %s." % archive_path)
|
||||
|
||||
def validate_metadata(self, metadata_url=None):
|
||||
"""Validates received the metadata files."""
|
||||
print("Running validation of the metadata files")
|
||||
if metadata_url:
|
||||
metadata_name = metadata_url.replace(
|
||||
FWUPD_DOWNLOAD_PREFIX,
|
||||
""
|
||||
)
|
||||
metadata_file = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
metadata_name
|
||||
)
|
||||
metadata_name = metadata_url.replace(FWUPD_DOWNLOAD_PREFIX, "")
|
||||
metadata_file = os.path.join(FWUPD_VM_METADATA_DIR, metadata_name)
|
||||
else:
|
||||
metadata_file = FWUPD_VM_METADATA_FILE
|
||||
try:
|
||||
self._jcat_verification(
|
||||
f"{metadata_file}.jcat",
|
||||
FWUPD_VM_METADATA_DIR
|
||||
)
|
||||
self._jcat_verification(f"{metadata_file}.jcat", FWUPD_VM_METADATA_DIR)
|
||||
except Exception as e:
|
||||
print(str(e), file=sys.stderr)
|
||||
self.clean_vm_cache()
|
||||
@ -113,10 +86,7 @@ class FwupdUsbvmUpdates(FwupdVmCommon):
|
||||
arch_temp = os.path.join(output_path, archive_name)
|
||||
os.mkdir(output_path)
|
||||
shutil.copyfile(archive_path, arch_temp)
|
||||
self._extract_archive(
|
||||
arch_temp,
|
||||
output_path
|
||||
)
|
||||
self._extract_archive(arch_temp, output_path)
|
||||
signature_name = os.path.join(output_path, "firmware*.jcat")
|
||||
file_path = glob.glob(signature_name)
|
||||
try:
|
||||
@ -145,8 +115,7 @@ def main():
|
||||
f.clean_vm_cache()
|
||||
elif sys.argv[1] == "updates" and len(sys.argv) < 4:
|
||||
raise Exception(
|
||||
"Invalid number of arguments.\n"
|
||||
"Expected archive path and checksum."
|
||||
"Invalid number of arguments.\n" "Expected archive path and checksum."
|
||||
)
|
||||
elif sys.argv[1] == "updates" and not len(sys.argv) < 4:
|
||||
f.validate_updates(sys.argv[2], sys.argv[3])
|
||||
@ -154,5 +123,5 @@ def main():
|
||||
raise Exception("Invalid command")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -26,21 +26,15 @@ QUBES_FWUPDMGR_BINDIR = "/usr/sbin/qubes-fwupdmgr"
|
||||
class TestQubesFwupdHeads(unittest.TestCase):
|
||||
def setUp(self):
|
||||
if os.path.exists(QUBES_FWUPDMGR_REPO):
|
||||
self.qfwupd = imp.load_source(
|
||||
"qubes_fwupdmgr",
|
||||
QUBES_FWUPDMGR_REPO
|
||||
)
|
||||
self.qfwupd = imp.load_source("qubes_fwupdmgr", QUBES_FWUPDMGR_REPO)
|
||||
elif os.path.exists(QUBES_FWUPDMGR_BINDIR):
|
||||
self.qfwupd = imp.load_source(
|
||||
"qubes_fwupdmgr",
|
||||
QUBES_FWUPDMGR_BINDIR
|
||||
)
|
||||
self.qfwupd = imp.load_source("qubes_fwupdmgr", QUBES_FWUPDMGR_BINDIR)
|
||||
self.q = qf_heads.FwupdHeads()
|
||||
self.maxDiff = 2000
|
||||
self.captured_output = io.StringIO()
|
||||
sys.stdout = self.captured_output
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_get_hwids(self):
|
||||
self.q._check_fwupdtool_version()
|
||||
self.q._get_hwids()
|
||||
@ -56,12 +50,11 @@ class TestQubesFwupdHeads(unittest.TestCase):
|
||||
self.q._gather_firmware_version()
|
||||
self.assertEqual(self.q.heads_version, "0.2.2")
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_parse_metadata(self):
|
||||
qmgr = self.qfwupd.QubesFwupdmgr()
|
||||
qmgr.metadata_file = CUSTOM_METADATA.replace(
|
||||
"https://fwupd.org/downloads",
|
||||
self.qfwupd.FWUPD_DOM0_METADATA_DIR
|
||||
"https://fwupd.org/downloads", self.qfwupd.FWUPD_DOM0_METADATA_DIR
|
||||
)
|
||||
qmgr._download_metadata(metadata_url=CUSTOM_METADATA)
|
||||
self.q._parse_metadata(qmgr.metadata_file)
|
||||
@ -74,16 +67,12 @@ class TestQubesFwupdHeads(unittest.TestCase):
|
||||
self.assertEqual(return_code, 0)
|
||||
self.assertEqual(
|
||||
self.q.heads_update_url,
|
||||
"https://fwupd.org/downloads/e747a435bf24fd6081b77b6704b39cec5fa2dcf62e0ca6b86d8a6460121a1d07-heads_coreboot_x230-v0_2_3.cab"
|
||||
"https://fwupd.org/downloads/e747a435bf24fd6081b77b6704b39cec5fa2dcf62e0ca6b86d8a6460121a1d07-heads_coreboot_x230-v0_2_3.cab",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.heads_update_sha,
|
||||
"1a54e69ca2b58d1218035115d481480eaf4c66e4"
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.heads_update_version,
|
||||
"0.2.3"
|
||||
self.q.heads_update_sha, "1a54e69ca2b58d1218035115d481480eaf4c66e4"
|
||||
)
|
||||
self.assertEqual(self.q.heads_update_version, "0.2.3")
|
||||
|
||||
def test_check_heads_updates_no_updates(self):
|
||||
self.q.metadata_info = HEADS_XML
|
||||
@ -98,30 +87,24 @@ class TestQubesFwupdHeads(unittest.TestCase):
|
||||
self.assertEqual(return_code, 0)
|
||||
self.assertEqual(
|
||||
self.q.heads_update_url,
|
||||
"https://fwupd.org/downloads/e747a435bf24fd6081b77b6704b39cec5fa2dcf62e0ca6b86d8a6460121a1d07-heads_coreboot_x230-v0_2_3.cab"
|
||||
"https://fwupd.org/downloads/e747a435bf24fd6081b77b6704b39cec5fa2dcf62e0ca6b86d8a6460121a1d07-heads_coreboot_x230-v0_2_3.cab",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.heads_update_sha,
|
||||
"1a54e69ca2b58d1218035115d481480eaf4c66e4"
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.heads_update_version,
|
||||
"0.2.3"
|
||||
self.q.heads_update_sha, "1a54e69ca2b58d1218035115d481480eaf4c66e4"
|
||||
)
|
||||
self.assertEqual(self.q.heads_update_version, "0.2.3")
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_copy_heads_firmware(self):
|
||||
qmgr = self.qfwupd.QubesFwupdmgr()
|
||||
self.q.heads_update_url = "https://fwupd.org/downloads/e747a435bf24fd6081b77b6704b39cec5fa2dcf62e0ca6b86d8a6460121a1d07-heads_coreboot_x230-v0_2_3.cab"
|
||||
self.q.heads_update_sha = "1a54e69ca2b58d1218035115d481480eaf4c66e4"
|
||||
self.q.heads_update_version = "0.2.3"
|
||||
qmgr._download_firmware_updates(
|
||||
self.q.heads_update_url,
|
||||
self.q.heads_update_sha
|
||||
self.q.heads_update_url, self.q.heads_update_sha
|
||||
)
|
||||
heads_boot_path = os.path.join(
|
||||
qf_heads.HEADS_UPDATES_DIR,
|
||||
self.q.heads_update_version
|
||||
qf_heads.HEADS_UPDATES_DIR, self.q.heads_update_version
|
||||
)
|
||||
if os.path.exists(heads_boot_path):
|
||||
shutil.rmtree(heads_boot_path)
|
||||
@ -131,5 +114,5 @@ class TestQubesFwupdHeads(unittest.TestCase):
|
||||
self.assertTrue(os.path.exists(firmware_path))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@ -26,39 +26,23 @@ QUBES_FWUPDMGR_REPO = "./src/qubes_fwupdmgr.py"
|
||||
QUBES_FWUPDMGR_BINDIR = "/usr/sbin/qubes-fwupdmgr"
|
||||
|
||||
if os.path.exists(QUBES_FWUPDMGR_REPO):
|
||||
qfwupd = imp.load_source(
|
||||
"qubes_fwupdmgr",
|
||||
QUBES_FWUPDMGR_REPO
|
||||
)
|
||||
qfwupd = imp.load_source("qubes_fwupdmgr", QUBES_FWUPDMGR_REPO)
|
||||
elif os.path.exists(QUBES_FWUPDMGR_BINDIR):
|
||||
qfwupd = imp.load_source(
|
||||
"qubes_fwupdmgr",
|
||||
QUBES_FWUPDMGR_BINDIR
|
||||
)
|
||||
qfwupd = imp.load_source("qubes_fwupdmgr", QUBES_FWUPDMGR_BINDIR)
|
||||
|
||||
FWUPD_DOM0_DIR = "/root/.cache/fwupd"
|
||||
FWUPD_DOM0_UPDATES_DIR = os.path.join(FWUPD_DOM0_DIR, "updates")
|
||||
FWUPD_DOM0_UNTRUSTED_DIR = os.path.join(FWUPD_DOM0_UPDATES_DIR, "untrusted")
|
||||
FWUPD_VM_LOG = os.path.join(FWUPD_DOM0_DIR, "usbvm-devices.log")
|
||||
FWUPD_DOM0_METADATA_DIR = os.path.join(FWUPD_DOM0_DIR, "metadata")
|
||||
FWUPD_DOM0_METADATA_FILE = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
FWUPD_DOM0_METADATA_FILE_JCAT = os.path.join(
|
||||
FWUPD_DOM0_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
FWUPD_DOM0_METADATA_FILE = os.path.join(FWUPD_DOM0_METADATA_DIR, "firmware.xml.gz")
|
||||
FWUPD_DOM0_METADATA_FILE_JCAT = os.path.join(FWUPD_DOM0_METADATA_DIR, "firmware.xml.gz")
|
||||
FWUPD_VM_DIR = "/home/user/.cache/fwupd"
|
||||
FWUPD_VM_UPDATES_DIR = os.path.join(FWUPD_VM_DIR, "updates")
|
||||
FWUPD_VM_METADATA_DIR = os.path.join(FWUPD_VM_DIR, "metadata")
|
||||
FWUPD_VM_METADATA_FILE = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz"
|
||||
)
|
||||
FWUPD_VM_METADATA_FILE = os.path.join(FWUPD_VM_METADATA_DIR, "firmware.xml.gz")
|
||||
FWUPD_VM_METADATA_FILE_JCAT = os.path.join(
|
||||
FWUPD_VM_METADATA_DIR,
|
||||
"firmware.xml.gz.jcat"
|
||||
FWUPD_VM_METADATA_DIR, "firmware.xml.gz.jcat"
|
||||
)
|
||||
REQUIRED_DEV = "Requires device not connected"
|
||||
REQUIRED_USBVM = "Requires sys-usb"
|
||||
@ -73,7 +57,7 @@ CUSTOM_METADATA = "https://fwupd.org/downloads/firmware-3c81bfdc9db5c8a42c09d380
|
||||
|
||||
def check_usbvm():
|
||||
"""Checks if sys-usb is running"""
|
||||
if 'qubes' not in platform.release():
|
||||
if "qubes" not in platform.release():
|
||||
return False
|
||||
q = qfwupd.QubesFwupdmgr()
|
||||
q.check_usbvm()
|
||||
@ -82,7 +66,7 @@ def check_usbvm():
|
||||
|
||||
def device_connected_dom0():
|
||||
"""Checks if the testing device is connected in dom0"""
|
||||
if 'qubes' not in platform.release():
|
||||
if "qubes" not in platform.release():
|
||||
return False
|
||||
q = qfwupd.QubesFwupdmgr()
|
||||
q._get_dom0_devices()
|
||||
@ -104,7 +88,7 @@ def device_connected_usbvm():
|
||||
|
||||
def check_whonix_updatevm():
|
||||
"""Checks if the sys-whonix is running"""
|
||||
if 'qubes' not in platform.release():
|
||||
if "qubes" not in platform.release():
|
||||
return False
|
||||
q = qfwupd.QubesFwupdmgr()
|
||||
q.check_usbvm()
|
||||
@ -118,7 +102,7 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.captured_output = io.StringIO()
|
||||
sys.stdout = self.captured_output
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_download_metadata(self):
|
||||
self.q.metadata_file = FWUPD_DOM0_METADATA_FILE
|
||||
self.q._download_metadata()
|
||||
@ -144,13 +128,12 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
msg="Metadata signature does not exist",
|
||||
)
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_download_custom_metadata(self):
|
||||
self.q.metadata_file = CUSTOM_METADATA.replace(
|
||||
"https://fwupd.org/downloads",
|
||||
FWUPD_DOM0_METADATA_DIR
|
||||
"https://fwupd.org/downloads", FWUPD_DOM0_METADATA_DIR
|
||||
)
|
||||
self.q.metadata_file_jcat = self.q.metadata_file + '.jcat'
|
||||
self.q.metadata_file_jcat = self.q.metadata_file + ".jcat"
|
||||
self.q._download_metadata(metadata_url=CUSTOM_METADATA)
|
||||
self.assertTrue(
|
||||
os.path.exists(self.q.metadata_file),
|
||||
@ -161,22 +144,22 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
msg="Metadata signature does not exist",
|
||||
)
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_refresh_metadata_dom0(self):
|
||||
self.q.refresh_metadata()
|
||||
self.assertEqual(
|
||||
self.q.output,
|
||||
'Successfully refreshed metadata manually\n',
|
||||
msg="Metadata refresh failed."
|
||||
"Successfully refreshed metadata manually\n",
|
||||
msg="Metadata refresh failed.",
|
||||
)
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_refresh_metadata_dom0_custom(self):
|
||||
self.q.refresh_metadata(metadata_url=CUSTOM_METADATA)
|
||||
self.assertEqual(
|
||||
self.q.output,
|
||||
'Successfully refreshed metadata manually\n',
|
||||
msg="Metadata refresh failed."
|
||||
"Successfully refreshed metadata manually\n",
|
||||
msg="Metadata refresh failed.",
|
||||
)
|
||||
|
||||
@unittest.skipUnless(check_usbvm(), REQUIRED_USBVM)
|
||||
@ -184,8 +167,8 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.q.refresh_metadata(usbvm=True)
|
||||
self.assertEqual(
|
||||
self.q.output,
|
||||
'Successfully refreshed metadata manually\n',
|
||||
msg="Metadata refresh failed."
|
||||
"Successfully refreshed metadata manually\n",
|
||||
msg="Metadata refresh failed.",
|
||||
)
|
||||
|
||||
@unittest.skipUnless(check_usbvm(), REQUIRED_USBVM)
|
||||
@ -193,8 +176,8 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.q.refresh_metadata(usbvm=True, metadata_url=CUSTOM_METADATA)
|
||||
self.assertEqual(
|
||||
self.q.output,
|
||||
'Successfully refreshed metadata manually\n',
|
||||
msg="Metadata refresh failed."
|
||||
"Successfully refreshed metadata manually\n",
|
||||
msg="Metadata refresh failed.",
|
||||
)
|
||||
|
||||
@unittest.skipUnless(check_whonix_updatevm(), "Requires sys-whonix")
|
||||
@ -202,64 +185,55 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.q.refresh_metadata(whonix=True)
|
||||
self.assertEqual(
|
||||
self.q.output,
|
||||
'Successfully refreshed metadata manually\n',
|
||||
msg="Metadata refresh failed."
|
||||
"Successfully refreshed metadata manually\n",
|
||||
msg="Metadata refresh failed.",
|
||||
)
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_get_dom0_updates(self):
|
||||
self.q._get_dom0_updates()
|
||||
self.assertIn(
|
||||
"Devices",
|
||||
self.q.dom0_updates_info,
|
||||
msg="Getting available updates failed"
|
||||
"Devices", self.q.dom0_updates_info, msg="Getting available updates failed"
|
||||
)
|
||||
|
||||
def test_parse_updates_info(self):
|
||||
self.q._parse_dom0_updates_info(UPDATE_INFO)
|
||||
self.assertEqual(
|
||||
self.q.dom0_updates_list[0]["Name"],
|
||||
"ColorHug2",
|
||||
msg="Wrong device name"
|
||||
self.q.dom0_updates_list[0]["Name"], "ColorHug2", msg="Wrong device name"
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.dom0_updates_list[0]["Version"],
|
||||
"2.0.6",
|
||||
msg="Wrong update version"
|
||||
self.q.dom0_updates_list[0]["Version"], "2.0.6", msg="Wrong update version"
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.dom0_updates_list[0]["Releases"][0]["Url"],
|
||||
"https://fwupd.org/downloads/0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7.cab",
|
||||
msg="Wrong update URL"
|
||||
msg="Wrong update URL",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.dom0_updates_list[0]["Releases"][0]["Checksum"],
|
||||
"32c4a2c9be787cdf1d757c489d6455bd7bb14053425180b6d331c37e1ccc1cda",
|
||||
msg="Wrong checksum"
|
||||
msg="Wrong checksum",
|
||||
)
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_download_firmware_updates(self):
|
||||
self.q._download_firmware_updates(
|
||||
"https://fwupd.org/downloads/0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7.cab",
|
||||
"32c4a2c9be787cdf1d757c489d6455bd7bb14053425180b6d331c37e1ccc1cda"
|
||||
"32c4a2c9be787cdf1d757c489d6455bd7bb14053425180b6d331c37e1ccc1cda",
|
||||
)
|
||||
update_path = os.path.join(
|
||||
FWUPD_DOM0_UPDATES_DIR,
|
||||
"0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7"
|
||||
"0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7",
|
||||
)
|
||||
self.assertTrue(os.path.exists(update_path))
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_download_firmware_special_char(self):
|
||||
self.q._download_firmware_updates(
|
||||
"https://fwupd.org/downloads/bc334d8b098f2e91603c5f7dfdc837fb01797bbe-Dell%20XPS%2015%209560&Precision%205520%20System%20BIOS_Ver.1.18.0.cab",
|
||||
"86d9e5e35b0b264be1bb1e49ec16ccd1330390423bfe962267a58c27be7712b8"
|
||||
)
|
||||
update_path = os.path.join(
|
||||
FWUPD_DOM0_UPDATES_DIR,
|
||||
"trusted"
|
||||
"86d9e5e35b0b264be1bb1e49ec16ccd1330390423bfe962267a58c27be7712b8",
|
||||
)
|
||||
update_path = os.path.join(FWUPD_DOM0_UPDATES_DIR, "trusted")
|
||||
self.assertTrue(os.path.exists(update_path))
|
||||
|
||||
@unittest.skipUnless(check_whonix_updatevm(), "Requires sys-whonix")
|
||||
@ -271,62 +245,53 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
)
|
||||
update_path = os.path.join(
|
||||
FWUPD_DOM0_UPDATES_DIR,
|
||||
"0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7"
|
||||
"0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7",
|
||||
)
|
||||
self.assertTrue(os.path.exists(update_path))
|
||||
|
||||
def test_user_input_empty_dict(self):
|
||||
downgrade_dict = {
|
||||
"usbvm": [],
|
||||
"dom0": []
|
||||
}
|
||||
downgrade_dict = {"usbvm": [], "dom0": []}
|
||||
self.assertEqual(self.q._user_input(downgrade_dict), 2)
|
||||
|
||||
def test_user_input_n(self):
|
||||
user_input = ['sth', 'n']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = ["sth", "n"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q._parse_dom0_updates_info(UPDATE_INFO)
|
||||
downgrade_dict = {
|
||||
"usbvm": self.q.dom0_updates_list,
|
||||
"dom0": self.q.dom0_updates_list
|
||||
"dom0": self.q.dom0_updates_list,
|
||||
}
|
||||
choice = self.q._user_input(
|
||||
downgrade_dict,
|
||||
usbvm=True
|
||||
)
|
||||
choice = self.q._user_input(downgrade_dict, usbvm=True)
|
||||
self.assertEqual(choice, 2)
|
||||
user_input = ['sth', 'N']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = ["sth", "N"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q._parse_dom0_updates_info(UPDATE_INFO)
|
||||
downgrade_dict = {
|
||||
"usbvm": self.q.dom0_updates_list,
|
||||
"dom0": self.q.dom0_updates_list
|
||||
"dom0": self.q.dom0_updates_list,
|
||||
}
|
||||
choice = self.q._user_input(
|
||||
downgrade_dict,
|
||||
usbvm=True
|
||||
)
|
||||
choice = self.q._user_input(downgrade_dict, usbvm=True)
|
||||
self.assertEqual(choice, 2)
|
||||
|
||||
def test_user_input_choice(self):
|
||||
user_input = ['6', '1']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = ["6", "1"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q._parse_dom0_updates_info(UPDATE_INFO)
|
||||
updates_dict = {
|
||||
"usbvm": self.q.dom0_updates_list,
|
||||
"dom0": self.q.dom0_updates_list
|
||||
"dom0": self.q.dom0_updates_list,
|
||||
}
|
||||
key, choice = self.q._user_input(updates_dict)
|
||||
self.assertEqual(key, "dom0")
|
||||
self.assertEqual(choice, 0)
|
||||
|
||||
def test_user_input_choice_usbvm(self):
|
||||
user_input = ['6', '2']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = ["6", "2"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q._parse_dom0_updates_info(UPDATE_INFO)
|
||||
updates_dict = {
|
||||
"usbvm": self.q.dom0_updates_list,
|
||||
"dom0": self.q.dom0_updates_list
|
||||
"dom0": self.q.dom0_updates_list,
|
||||
}
|
||||
key, choice = self.q._user_input(updates_dict, usbvm=True)
|
||||
self.assertEqual(key, "usbvm")
|
||||
@ -338,18 +303,15 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.q._parse_parameters(update_dict, "dom0", 0)
|
||||
self.assertEqual(
|
||||
self.q.url,
|
||||
"https://fwupd.org/downloads/0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7.cab"
|
||||
"https://fwupd.org/downloads/0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7.cab",
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.sha,
|
||||
"32c4a2c9be787cdf1d757c489d6455bd7bb14053425180b6d331c37e1ccc1cda"
|
||||
)
|
||||
self.assertEqual(
|
||||
self.q.version,
|
||||
"2.0.7"
|
||||
"32c4a2c9be787cdf1d757c489d6455bd7bb14053425180b6d331c37e1ccc1cda",
|
||||
)
|
||||
self.assertEqual(self.q.version, "2.0.7")
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_clean_cache_dom0(self):
|
||||
self.q.clean_cache()
|
||||
self.assertFalse(os.path.exists(FWUPD_DOM0_METADATA_DIR))
|
||||
@ -365,28 +327,20 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
f"! [ -d {FWUPD_VM_METADATA_DIR} ]"
|
||||
f"! [ -d {FWUPD_VM_METADATA_DIR} ]",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_metadata)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Creating metadata directory failed"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Creating metadata directory failed")
|
||||
cmd_validate_udpdate = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
f"! [ -d {FWUPD_VM_UPDATES_DIR} ]"
|
||||
f"! [ -d {FWUPD_VM_UPDATES_DIR} ]",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_udpdate)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Cleaning update directory failed"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Cleaning update directory failed")
|
||||
|
||||
def test_output_crawler(self):
|
||||
crawler_output = io.StringIO()
|
||||
@ -394,17 +348,16 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.q._output_crawler(json.loads(UPDATE_INFO), 0)
|
||||
with open("test/logs/get_devices.log", "r") as get_devices:
|
||||
self.assertEqual(
|
||||
get_devices.read(),
|
||||
crawler_output.getvalue().strip() + "\n"
|
||||
get_devices.read(), crawler_output.getvalue().strip() + "\n"
|
||||
)
|
||||
sys.stdout = self.captured_output
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_get_dom0_devices(self):
|
||||
self.q._get_dom0_devices()
|
||||
self.assertIsNotNone(self.q.dom0_devices_info)
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_get_devices_qubes_dom0(self):
|
||||
get_devices_output = io.StringIO()
|
||||
sys.stdout = get_devices_output
|
||||
@ -441,45 +394,36 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
sys.stdout = help_output
|
||||
self.q.help()
|
||||
with open("test/logs/help.log", "r") as help_log:
|
||||
self.assertEqual(
|
||||
help_log.read(),
|
||||
help_output.getvalue().strip() + "\n"
|
||||
)
|
||||
self.assertEqual(help_log.read(), help_output.getvalue().strip() + "\n")
|
||||
sys.stdout = self.captured_output
|
||||
|
||||
@patch(
|
||||
'test.test_qubes_fwupdmgr.qfwupd.QubesFwupdmgr._read_dmi',
|
||||
return_value=DMI_DECODE
|
||||
"test.test_qubes_fwupdmgr.qfwupd.QubesFwupdmgr._read_dmi",
|
||||
return_value=DMI_DECODE,
|
||||
)
|
||||
def test_verify_dmi(self, output):
|
||||
self.q.dmi_version = "P.1.0"
|
||||
self.q._verify_dmi("test/logs/", "P1.1")
|
||||
|
||||
@patch(
|
||||
'test.test_qubes_fwupdmgr.qfwupd.QubesFwupdmgr._read_dmi',
|
||||
return_value=DMI_DECODE
|
||||
"test.test_qubes_fwupdmgr.qfwupd.QubesFwupdmgr._read_dmi",
|
||||
return_value=DMI_DECODE,
|
||||
)
|
||||
def test_verify_dmi_wrong_vendor(self, output):
|
||||
with self.assertRaises(ValueError) as wrong_vendor:
|
||||
self.q.dmi_version = "P.1.0"
|
||||
self.q._verify_dmi("test/logs/metainfo_name/", "P1.1")
|
||||
self.assertIn(
|
||||
"Wrong firmware provider.",
|
||||
str(wrong_vendor.exception)
|
||||
)
|
||||
self.assertIn("Wrong firmware provider.", str(wrong_vendor.exception))
|
||||
|
||||
@patch(
|
||||
'test.test_qubes_fwupdmgr.qfwupd.QubesFwupdmgr._read_dmi',
|
||||
return_value=DMI_DECODE
|
||||
"test.test_qubes_fwupdmgr.qfwupd.QubesFwupdmgr._read_dmi",
|
||||
return_value=DMI_DECODE,
|
||||
)
|
||||
def test_verify_dmi_version(self, output):
|
||||
self.q.dmi_version = "P1.0"
|
||||
with self.assertRaises(ValueError) as downgrade:
|
||||
self.q._verify_dmi("test/logs/metainfo_version/", "P0.1")
|
||||
self.assertIn(
|
||||
"P0.1 < P1.0 Downgrade not allowed",
|
||||
str(downgrade.exception)
|
||||
)
|
||||
self.assertIn("P0.1 < P1.0 Downgrade not allowed", str(downgrade.exception))
|
||||
|
||||
@unittest.skipUnless(device_connected_dom0(), REQUIRED_DEV)
|
||||
def test_downgrade_firmware_dom0(self):
|
||||
@ -494,8 +438,8 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
break
|
||||
if old_version is None:
|
||||
self.fail("Test device not found")
|
||||
user_input = [str(number+1), '1']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = [str(number + 1), "1"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q.downgrade_firmware()
|
||||
self.q._get_dom0_devices()
|
||||
downgrades = self.q._parse_downgrades(self.q.dom0_devices_info)
|
||||
@ -503,16 +447,13 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.assertGreater(l_ver(old_version), l_ver(new_version))
|
||||
|
||||
@unittest.skipUnless(
|
||||
check_whonix_updatevm() and device_connected_usbvm(),
|
||||
REQUIRED_DEV
|
||||
check_whonix_updatevm() and device_connected_usbvm(), REQUIRED_DEV
|
||||
)
|
||||
def test_update_n_downgrade_firmware_whonix(self):
|
||||
old_version = None
|
||||
self.q.clean_cache(usbvm=True)
|
||||
self.q._get_dom0_devices()
|
||||
dom0_downgrades = self.q._parse_downgrades(
|
||||
self.q.dom0_devices_info
|
||||
)
|
||||
dom0_downgrades = self.q._parse_downgrades(self.q.dom0_devices_info)
|
||||
self.q._get_usbvm_devices()
|
||||
with open(FWUPD_VM_LOG) as usbvm_device_info:
|
||||
raw = usbvm_device_info.read()
|
||||
@ -525,8 +466,8 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
break
|
||||
if old_version is None:
|
||||
self.fail("Test device not found")
|
||||
user_input = [str(number+1+len(dom0_downgrades)), '1']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = [str(number + 1 + len(dom0_downgrades)), "1"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q.downgrade_firmware(usbvm=True, whonix=True)
|
||||
self.q._get_usbvm_devices()
|
||||
with open(FWUPD_VM_LOG) as usbvm_device_info:
|
||||
@ -550,8 +491,8 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
break
|
||||
if old_version is None:
|
||||
self.fail("Test device not found")
|
||||
user_input = [str(number+1+len(self.q.dom0_updates_list)), '1']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = [str(number + 1 + len(self.q.dom0_updates_list)), "1"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q.update_firmware(usbvm=True, whonix=True)
|
||||
self.q._get_usbvm_devices()
|
||||
with open(FWUPD_VM_LOG) as usbvm_device_info:
|
||||
@ -571,9 +512,7 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
def test_downgrade_firmware_usbvm(self):
|
||||
old_version = None
|
||||
self.q._get_dom0_devices()
|
||||
dom0_downgrades = self.q._parse_downgrades(
|
||||
self.q.dom0_devices_info
|
||||
)
|
||||
dom0_downgrades = self.q._parse_downgrades(self.q.dom0_devices_info)
|
||||
self.q._get_usbvm_devices()
|
||||
with open(FWUPD_VM_LOG) as usbvm_device_info:
|
||||
raw = usbvm_device_info.read()
|
||||
@ -586,8 +525,8 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
break
|
||||
if old_version is None:
|
||||
self.fail("Test device not found")
|
||||
user_input = [str(number+1+len(dom0_downgrades)), '1']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = [str(number + 1 + len(dom0_downgrades)), "1"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q.downgrade_firmware(usbvm=True)
|
||||
self.q._get_usbvm_devices()
|
||||
with open(FWUPD_VM_LOG) as usbvm_device_info:
|
||||
@ -598,95 +537,62 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
|
||||
def test_parse_downgrades(self):
|
||||
downgrades = self.q._parse_downgrades(GET_DEVICES)
|
||||
self.assertEqual(
|
||||
downgrades[0]["Name"],
|
||||
"ColorHug2"
|
||||
)
|
||||
self.assertEqual(
|
||||
downgrades[0]["Version"],
|
||||
"2.0.6"
|
||||
)
|
||||
self.assertEqual(
|
||||
downgrades[0]["Releases"][0]["Version"],
|
||||
"2.0.5"
|
||||
)
|
||||
self.assertEqual(downgrades[0]["Name"], "ColorHug2")
|
||||
self.assertEqual(downgrades[0]["Version"], "2.0.6")
|
||||
self.assertEqual(downgrades[0]["Releases"][0]["Version"], "2.0.5")
|
||||
self.assertEqual(
|
||||
downgrades[0]["Releases"][0]["Url"],
|
||||
"https://fwupd.org/downloads/f7dd4ab29fa610438571b8b62b26b0b0e57bb35b-hughski-colorhug2-2.0.5.cab"
|
||||
"https://fwupd.org/downloads/f7dd4ab29fa610438571b8b62b26b0b0e57bb35b-hughski-colorhug2-2.0.5.cab",
|
||||
)
|
||||
self.assertEqual(
|
||||
downgrades[0]["Releases"][0]["Checksum"],
|
||||
"8cd379eb2e1467e4fda92c20650306dc7e598b1d421841bbe19d9ed6ea01e3ee"
|
||||
"8cd379eb2e1467e4fda92c20650306dc7e598b1d421841bbe19d9ed6ea01e3ee",
|
||||
)
|
||||
|
||||
def test_parse_downgrades_no_version(self):
|
||||
downgrades = self.q._parse_downgrades(GET_DEVICES_NO_VERSION)
|
||||
self.assertEqual(
|
||||
downgrades[0]["Name"],
|
||||
"ColorHug2"
|
||||
)
|
||||
self.assertEqual(
|
||||
downgrades[0]["Version"],
|
||||
"2.0.6"
|
||||
)
|
||||
self.assertEqual(
|
||||
downgrades[0]["Releases"][0]["Version"],
|
||||
"2.0.5"
|
||||
)
|
||||
self.assertEqual(downgrades[0]["Name"], "ColorHug2")
|
||||
self.assertEqual(downgrades[0]["Version"], "2.0.6")
|
||||
self.assertEqual(downgrades[0]["Releases"][0]["Version"], "2.0.5")
|
||||
self.assertEqual(
|
||||
downgrades[0]["Releases"][0]["Url"],
|
||||
"https://fwupd.org/downloads/f7dd4ab29fa610438571b8b62b26b0b0e57bb35b-hughski-colorhug2-2.0.5.cab"
|
||||
"https://fwupd.org/downloads/f7dd4ab29fa610438571b8b62b26b0b0e57bb35b-hughski-colorhug2-2.0.5.cab",
|
||||
)
|
||||
self.assertEqual(
|
||||
downgrades[0]["Releases"][0]["Checksum"],
|
||||
"4ee9dfa38df3b810f739d8a19d13da1b3175fb87"
|
||||
"4ee9dfa38df3b810f739d8a19d13da1b3175fb87",
|
||||
)
|
||||
|
||||
def test_user_input_downgrade_usbvm(self):
|
||||
user_input = ['2', '6', 'sth', '2.2.1', '', ' ', '\0', '2']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = ["2", "6", "sth", "2.2.1", "", " ", "\0", "2"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
downgrade_list = self.q._parse_downgrades(GET_DEVICES)
|
||||
downgrade_dict = {
|
||||
"usbvm": downgrade_list,
|
||||
"dom0": downgrade_list
|
||||
}
|
||||
downgrade_dict = {"usbvm": downgrade_list, "dom0": downgrade_list}
|
||||
key, device_choice, downgrade_choice = self.q._user_input(
|
||||
downgrade_dict,
|
||||
downgrade=True,
|
||||
usbvm=True
|
||||
downgrade_dict, downgrade=True, usbvm=True
|
||||
)
|
||||
self.assertEqual(key, "usbvm")
|
||||
self.assertEqual(device_choice, 0)
|
||||
self.assertEqual(downgrade_choice, 1)
|
||||
|
||||
def test_user_input_downgrade_dom0(self):
|
||||
user_input = ['1', '6', 'sth', '2.2.1', '', ' ', '\0', '2']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = ["1", "6", "sth", "2.2.1", "", " ", "\0", "2"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
downgrade_list = self.q._parse_downgrades(GET_DEVICES)
|
||||
downgrade_dict = {
|
||||
"dom0": downgrade_list
|
||||
}
|
||||
downgrade_dict = {"dom0": downgrade_list}
|
||||
key, device_choice, downgrade_choice = self.q._user_input(
|
||||
downgrade_dict,
|
||||
downgrade=True,
|
||||
downgrade_dict, downgrade=True
|
||||
)
|
||||
self.assertEqual(key, "dom0")
|
||||
self.assertEqual(device_choice, 0)
|
||||
self.assertEqual(downgrade_choice, 1)
|
||||
|
||||
def test_user_input_downgrade_N(self):
|
||||
user_input = ['N']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = ["N"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
downgrade_list = self.q._parse_downgrades(GET_DEVICES)
|
||||
downgrade_dict = {
|
||||
"usbvm": downgrade_list,
|
||||
"dom0": downgrade_list
|
||||
}
|
||||
N_choice = self.q._user_input(
|
||||
downgrade_dict,
|
||||
downgrade=True,
|
||||
usbvm=True
|
||||
)
|
||||
downgrade_dict = {"usbvm": downgrade_list, "dom0": downgrade_list}
|
||||
N_choice = self.q._user_input(downgrade_dict, downgrade=True, usbvm=True)
|
||||
self.assertEqual(N_choice, 2)
|
||||
|
||||
@unittest.skipUnless(device_connected_dom0(), REQUIRED_DEV)
|
||||
@ -703,8 +609,8 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
break
|
||||
if old_version is None:
|
||||
self.fail("Test device not found")
|
||||
user_input = [str(number+1)]
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = [str(number + 1)]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q.update_firmware()
|
||||
self.q._get_dom0_devices()
|
||||
dom0_devices_info_dict = json.loads(self.q.dom0_devices_info)
|
||||
@ -736,8 +642,8 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
break
|
||||
if old_version is None:
|
||||
self.fail("Test device not found")
|
||||
user_input = [str(number+1+len(self.q.dom0_updates_list)), '1']
|
||||
with patch('builtins.input', side_effect=user_input):
|
||||
user_input = [str(number + 1 + len(self.q.dom0_updates_list)), "1"]
|
||||
with patch("builtins.input", side_effect=user_input):
|
||||
self.q.update_firmware(usbvm=True)
|
||||
self.q._get_usbvm_devices()
|
||||
with open(FWUPD_VM_LOG) as usbvm_device_info:
|
||||
@ -766,13 +672,13 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.q.usbvm_updates_list[0]["Releases"],
|
||||
[
|
||||
{
|
||||
'Checksum': '32c4a2c9be787cdf1d757c489d6455bd7bb14053425180b6d331c37e1ccc1cda',
|
||||
'Description': '<p>This release fixes prevents the firmware returning an '
|
||||
'error when the remote SHA1 hash was never sent.</p>',
|
||||
'Url': 'https://fwupd.org/downloads/0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7.cab',
|
||||
'Version': '2.0.7'
|
||||
"Checksum": "32c4a2c9be787cdf1d757c489d6455bd7bb14053425180b6d331c37e1ccc1cda",
|
||||
"Description": "<p>This release fixes prevents the firmware returning an "
|
||||
"error when the remote SHA1 hash was never sent.</p>",
|
||||
"Url": "https://fwupd.org/downloads/0a29848de74d26348bc5a6e24fc9f03778eddf0e-hughski-colorhug2-2.0.7.cab",
|
||||
"Version": "2.0.7",
|
||||
}
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
def test_parse_usbvm_updates_no_updates_available(self):
|
||||
@ -786,8 +692,7 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.q._updates_crawler(self.q.usbvm_updates_list, usbvm=True)
|
||||
with open("test/logs/get_updates.log", "r") as getupdates:
|
||||
self.assertEqual(
|
||||
getupdates.read(),
|
||||
crawler_output.getvalue().strip() + "\n"
|
||||
getupdates.read(), crawler_output.getvalue().strip() + "\n"
|
||||
)
|
||||
sys.stdout = self.captured_output
|
||||
|
||||
@ -798,33 +703,25 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
f"[ -d {FWUPD_VM_METADATA_DIR} ]"
|
||||
f"[ -d {FWUPD_VM_METADATA_DIR} ]",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_metadata)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Creating metadata directory failed"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Creating metadata directory failed")
|
||||
cmd_validate_udpdate = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
f"[ -d {FWUPD_VM_UPDATES_DIR} ]"
|
||||
f"[ -d {FWUPD_VM_UPDATES_DIR} ]",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_udpdate)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Creating update directory failed"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Creating update directory failed")
|
||||
|
||||
@unittest.skipUnless(check_usbvm(), REQUIRED_USBVM)
|
||||
def test_copy_usbvm_metadata(self):
|
||||
self.q.metadata_file = FWUPD_DOM0_METADATA_FILE
|
||||
self.q.metadata_file_jcat = self.q.metadata_file + '.jcat'
|
||||
self.q.metadata_file_jcat = self.q.metadata_file + ".jcat"
|
||||
self.q._download_metadata()
|
||||
self.q._validate_usbvm_dirs()
|
||||
self.q._copy_usbvm_metadata()
|
||||
@ -832,30 +729,22 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
f"[ -f {FWUPD_VM_METADATA_FILE} ]"
|
||||
f"[ -f {FWUPD_VM_METADATA_FILE} ]",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_metadata_file)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Metadata file does not exist"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Metadata file does not exist")
|
||||
cmd_validate_metadata_jcat = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
f"[ -f {FWUPD_VM_METADATA_FILE_JCAT} ]"
|
||||
f"[ -f {FWUPD_VM_METADATA_FILE_JCAT} ]",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_metadata_jcat)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Metadata jcat signature does not exist"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Metadata jcat signature does not exist")
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_enable_lvfs_testing_dom0(self):
|
||||
if os.path.exists(LVFS_TESTING_DOM0_FLAG):
|
||||
os.remove(LVFS_TESTING_DOM0_FLAG)
|
||||
@ -869,18 +758,15 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
"script --quiet --return --command "
|
||||
f'"ls {LVFS_TESTING_USBVM_FLAG} &>/dev/null"'
|
||||
)
|
||||
),
|
||||
]
|
||||
cmd_rm_flag = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
USBVM_N,
|
||||
(
|
||||
'script --quiet --return --command '
|
||||
f'"rm {LVFS_TESTING_USBVM_FLAG}"'
|
||||
)
|
||||
("script --quiet --return --command " f'"rm {LVFS_TESTING_USBVM_FLAG}"'),
|
||||
]
|
||||
flag = subprocess.Popen(cmd_validate_flag)
|
||||
flag.wait()
|
||||
@ -897,7 +783,7 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
@unittest.skipUnless(check_usbvm(), REQUIRED_USBVM)
|
||||
def test_validate_usbvm_metadata(self):
|
||||
self.q.metadata_file = FWUPD_DOM0_METADATA_FILE
|
||||
self.q.metadata_file_jcat = self.q.metadata_file + '.jcat'
|
||||
self.q.metadata_file_jcat = self.q.metadata_file + ".jcat"
|
||||
self.q._download_metadata()
|
||||
self.q._validate_usbvm_dirs()
|
||||
self.q._copy_usbvm_metadata()
|
||||
@ -906,7 +792,7 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
@unittest.skipUnless(check_usbvm(), REQUIRED_USBVM)
|
||||
def test_refresh_usbvm_metadata(self):
|
||||
self.q.metadata_file = FWUPD_DOM0_METADATA_FILE
|
||||
self.q.metadata_file_jcat = self.q.metadata_file + '.jcat'
|
||||
self.q.metadata_file_jcat = self.q.metadata_file + ".jcat"
|
||||
self.q.lvfs = "lvfs"
|
||||
self.q._download_metadata()
|
||||
self.q._validate_usbvm_dirs()
|
||||
@ -922,28 +808,20 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
f"! [ -d {FWUPD_VM_METADATA_DIR} ]"
|
||||
f"! [ -d {FWUPD_VM_METADATA_DIR} ]",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_metadata)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Cleaning metadata directory failed"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Cleaning metadata directory failed")
|
||||
cmd_validate_udpdate = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
f"! [ -d {FWUPD_VM_METADATA_DIR} ]"
|
||||
f"! [ -d {FWUPD_VM_METADATA_DIR} ]",
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_udpdate)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Cleaning update directory failed"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Cleaning update directory failed")
|
||||
|
||||
@unittest.skipUnless(check_usbvm(), REQUIRED_USBVM)
|
||||
def test_validate_usbvm_archive(self):
|
||||
@ -952,46 +830,33 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
name = url.replace("https://fwupd.org/downloads/", "")
|
||||
self.q._clean_usbvm()
|
||||
self.q._validate_usbvm_dirs()
|
||||
self.q._download_firmware_updates(
|
||||
url,
|
||||
sha
|
||||
)
|
||||
self.q._copy_firmware_updates(
|
||||
name
|
||||
)
|
||||
self.q._validate_usbvm_archive(
|
||||
name,
|
||||
sha
|
||||
)
|
||||
self.q._download_firmware_updates(url, sha)
|
||||
self.q._copy_firmware_updates(name)
|
||||
self.q._validate_usbvm_archive(name, sha)
|
||||
cmd_validate_udpdate = [
|
||||
"qvm-run",
|
||||
"--pass-io",
|
||||
"sys-usb",
|
||||
"[ -f %s ]" %
|
||||
os.path.join(FWUPD_VM_UPDATES_DIR, name)
|
||||
"[ -f %s ]" % os.path.join(FWUPD_VM_UPDATES_DIR, name),
|
||||
]
|
||||
p = subprocess.Popen(cmd_validate_udpdate)
|
||||
p.wait()
|
||||
self.assertEqual(
|
||||
p.returncode,
|
||||
0,
|
||||
msg="Archive validation failed"
|
||||
)
|
||||
self.assertEqual(p.returncode, 0, msg="Archive validation failed")
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_check_usbvm(self):
|
||||
self.q.check_usbvm()
|
||||
self.assertIn(XL_LIST_LOG, self.q.output)
|
||||
|
||||
@unittest.skipUnless('qubes' in platform.release(), "Requires Qubes OS")
|
||||
@unittest.skipUnless("qubes" in platform.release(), "Requires Qubes OS")
|
||||
def test_bios_refresh_metadata(self):
|
||||
sys_usb = self.q.check_usbvm()
|
||||
Path(BIOS_UPDATE_FLAG).touch(mode=0o644, exist_ok=True)
|
||||
self.q.refresh_metadata_after_bios_update(usbvm=sys_usb)
|
||||
self.assertEqual(
|
||||
self.q.output,
|
||||
'Successfully refreshed metadata manually\n',
|
||||
msg="Metadata refresh failed."
|
||||
"Successfully refreshed metadata manually\n",
|
||||
msg="Metadata refresh failed.",
|
||||
)
|
||||
|
||||
@unittest.skipUnless(check_usbvm(), REQUIRED_USBVM)
|
||||
@ -1006,5 +871,5 @@ class TestQubesFwupdmgr(unittest.TestCase):
|
||||
self.assertFalse(os.path.exists(trusted_path.replace(".cab", "")))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@ -13,7 +13,7 @@ import shutil
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
TAG = b'#\x00'
|
||||
TAG = b"#\x00"
|
||||
|
||||
|
||||
def parse_args():
|
||||
@ -23,19 +23,19 @@ def parse_args():
|
||||
parser.add_argument("--directory", help="Directory to extract to")
|
||||
parser.add_argument(
|
||||
"--cleanup",
|
||||
action='store_true',
|
||||
action="store_true",
|
||||
help="Remove tools when done with installation",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--verbose", action='store_true', help="Run the tool in verbose mode"
|
||||
"--verbose", action="store_true", help="Run the tool in verbose mode"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--allow-reinstall",
|
||||
action='store_true',
|
||||
action="store_true",
|
||||
help="Allow re-installing existing firmware versions",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--allow-older", action='store_true', help="Allow downgrading firmware versions"
|
||||
"--allow-older", action="store_true", help="Allow downgrading firmware versions"
|
||||
)
|
||||
parser.add_argument(
|
||||
"command", choices=["install", "extract"], help="Command to run"
|
||||
@ -61,7 +61,7 @@ def bytes_slicer(length, source):
|
||||
def get_zip():
|
||||
script = os.path.realpath(__file__)
|
||||
bytes_out = io.BytesIO()
|
||||
with open(script, 'rb') as source:
|
||||
with open(script, "rb") as source:
|
||||
for line in source:
|
||||
if not line.startswith(TAG):
|
||||
continue
|
||||
@ -71,7 +71,7 @@ def get_zip():
|
||||
|
||||
def unzip(destination):
|
||||
zipf = get_zip()
|
||||
source = zipfile.ZipFile(zipf, 'r')
|
||||
source = zipfile.ZipFile(zipf, "r")
|
||||
for item in source.namelist():
|
||||
# extract handles the sanitization
|
||||
source.extract(item, destination)
|
||||
@ -83,7 +83,7 @@ def copy_cabs(source, target):
|
||||
cabs = []
|
||||
for root, dirs, files in os.walk(source):
|
||||
for f in files:
|
||||
if f.endswith('.cab'):
|
||||
if f.endswith(".cab"):
|
||||
origf = os.path.join(root, f)
|
||||
shutil.copy(origf, target)
|
||||
cabs.append(os.path.join(target, f))
|
||||
@ -91,31 +91,31 @@ def copy_cabs(source, target):
|
||||
|
||||
|
||||
def install_snap(directory, verbose, allow_reinstall, allow_older, uninstall):
|
||||
app = 'fwupd'
|
||||
common = '/root/snap/%s/common' % app
|
||||
app = "fwupd"
|
||||
common = "/root/snap/%s/common" % app
|
||||
|
||||
# check if snap is installed
|
||||
with open(os.devnull, 'w') as devnull:
|
||||
subprocess.run(['snap'], check=True, stdout=devnull, stderr=devnull)
|
||||
with open(os.devnull, "w") as devnull:
|
||||
subprocess.run(["snap"], check=True, stdout=devnull, stderr=devnull)
|
||||
|
||||
# check existing installed
|
||||
cmd = ['snap', 'list', app]
|
||||
with open(os.devnull, 'w') as devnull:
|
||||
cmd = ["snap", "list", app]
|
||||
with open(os.devnull, "w") as devnull:
|
||||
if verbose:
|
||||
print(cmd)
|
||||
ret = subprocess.run(cmd, stdout=devnull, stderr=devnull)
|
||||
if ret.returncode == 0:
|
||||
cmd = ['snap', 'remove', app]
|
||||
cmd = ["snap", "remove", app]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
# install the snap
|
||||
cmd = ['snap', 'ack', os.path.join(directory, 'fwupd.assert')]
|
||||
cmd = ["snap", "ack", os.path.join(directory, "fwupd.assert")]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, check=True)
|
||||
cmd = ['snap', 'install', '--classic', os.path.join(directory, 'fwupd.snap')]
|
||||
cmd = ["snap", "install", "--classic", os.path.join(directory, "fwupd.snap")]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, check=True)
|
||||
@ -125,7 +125,7 @@ def install_snap(directory, verbose, allow_reinstall, allow_older, uninstall):
|
||||
|
||||
# run the snap
|
||||
for cab in cabs:
|
||||
cmd = ["%s.fwupdmgr" % app, 'install', cab]
|
||||
cmd = ["%s.fwupdmgr" % app, "install", cab]
|
||||
if allow_reinstall:
|
||||
cmd += ["--allow-reinstall"]
|
||||
if allow_older:
|
||||
@ -141,61 +141,61 @@ def install_snap(directory, verbose, allow_reinstall, allow_older, uninstall):
|
||||
|
||||
# cleanup
|
||||
if uninstall:
|
||||
cmd = ['snap', 'remove', app]
|
||||
cmd = ["snap", "remove", app]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd)
|
||||
|
||||
|
||||
def install_flatpak(directory, verbose, allow_reinstall, allow_older, uninstall):
|
||||
app = 'org.freedesktop.fwupd'
|
||||
common = '%s/.var/app/%s' % (os.getenv('HOME'), app)
|
||||
app = "org.freedesktop.fwupd"
|
||||
common = "%s/.var/app/%s" % (os.getenv("HOME"), app)
|
||||
|
||||
with open(os.devnull, 'w') as devnull:
|
||||
with open(os.devnull, "w") as devnull:
|
||||
if not verbose:
|
||||
output = devnull
|
||||
else:
|
||||
output = None
|
||||
# look for dependencies
|
||||
dep = 'org.gnome.Platform/x86_64/3.30'
|
||||
repo = 'flathub'
|
||||
repo_url = 'https://flathub.org/repo/flathub.flatpakrepo'
|
||||
cmd = ['flatpak', 'info', dep]
|
||||
dep = "org.gnome.Platform/x86_64/3.30"
|
||||
repo = "flathub"
|
||||
repo_url = "https://flathub.org/repo/flathub.flatpakrepo"
|
||||
cmd = ["flatpak", "info", dep]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
ret = subprocess.run(cmd, stdout=output, stderr=output)
|
||||
# not installed
|
||||
if ret.returncode != 0:
|
||||
# look for remotes
|
||||
cmd = ['flatpak', 'remote-info', repo, dep]
|
||||
cmd = ["flatpak", "remote-info", repo, dep]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
ret = subprocess.run(cmd, stdout=output, stderr=output)
|
||||
# not enabled, enable it
|
||||
if ret.returncode != 0:
|
||||
cmd = ['flatpak', 'remote-add', repo, repo_url]
|
||||
cmd = ["flatpak", "remote-add", repo, repo_url]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
ret = subprocess.run(cmd, stderr=output)
|
||||
# install dep
|
||||
cmd = ['flatpak', 'install', repo, dep]
|
||||
cmd = ["flatpak", "install", repo, dep]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
ret = subprocess.run(cmd)
|
||||
|
||||
# check existing installed
|
||||
cmd = ['flatpak', 'info', app]
|
||||
cmd = ["flatpak", "info", app]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
ret = subprocess.run(cmd, stdout=output, stderr=output)
|
||||
if ret.returncode == 0:
|
||||
cmd = ['flatpak', 'remove', app]
|
||||
cmd = ["flatpak", "remove", app]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
# install the flatpak
|
||||
cmd = ['flatpak', 'install', os.path.join(directory, 'fwupd.flatpak')]
|
||||
cmd = ["flatpak", "install", os.path.join(directory, "fwupd.flatpak")]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, check=True)
|
||||
@ -205,7 +205,7 @@ def install_flatpak(directory, verbose, allow_reinstall, allow_older, uninstall)
|
||||
|
||||
# run command
|
||||
for cab in cabs:
|
||||
cmd = ['flatpak', 'run', app, 'install', cab]
|
||||
cmd = ["flatpak", "run", app, "install", cab]
|
||||
if allow_reinstall:
|
||||
cmd += ["--allow-reinstall"]
|
||||
if allow_older:
|
||||
@ -221,7 +221,7 @@ def install_flatpak(directory, verbose, allow_reinstall, allow_older, uninstall)
|
||||
|
||||
# cleanup
|
||||
if uninstall:
|
||||
cmd = ['flatpak', 'remove', app]
|
||||
cmd = ["flatpak", "remove", app]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd)
|
||||
@ -261,10 +261,10 @@ def remove_packaged_version(pkg, cache):
|
||||
res = False
|
||||
while True:
|
||||
res = input("Remove now (Y/N)? ")
|
||||
if res.lower() == 'n':
|
||||
if res.lower() == "n":
|
||||
res = False
|
||||
break
|
||||
if res.lower() == 'y':
|
||||
if res.lower() == "y":
|
||||
res = True
|
||||
break
|
||||
if res:
|
||||
@ -279,11 +279,11 @@ def install_builtin(directory, verbose, allow_reinstall, allow_older):
|
||||
cabs = []
|
||||
for root, dirs, files in os.walk(directory):
|
||||
for f in files:
|
||||
if f.endswith('.cab'):
|
||||
if f.endswith(".cab"):
|
||||
cabs.append(os.path.join(root, f))
|
||||
# run command
|
||||
for cab in cabs:
|
||||
cmd = ['fwupdmgr', 'install', cab]
|
||||
cmd = ["fwupdmgr", "install", cab]
|
||||
if allow_reinstall:
|
||||
cmd += ["--allow-reinstall"]
|
||||
if allow_older:
|
||||
@ -310,11 +310,11 @@ def run_installation(directory, verbose, allow_reinstall, allow_older, uninstall
|
||||
return
|
||||
|
||||
# determine what self extracting binary has
|
||||
if os.path.exists(os.path.join(directory, 'fwupd.snap')) and os.path.exists(
|
||||
os.path.join(directory, 'fwupd.assert')
|
||||
if os.path.exists(os.path.join(directory, "fwupd.snap")) and os.path.exists(
|
||||
os.path.join(directory, "fwupd.assert")
|
||||
):
|
||||
try_snap = True
|
||||
if os.path.exists(os.path.join(directory, 'fwupd.flatpak')):
|
||||
if os.path.exists(os.path.join(directory, "fwupd.flatpak")):
|
||||
try_flatpak = True
|
||||
|
||||
if try_snap:
|
||||
@ -330,9 +330,9 @@ def run_installation(directory, verbose, allow_reinstall, allow_older, uninstall
|
||||
install_flatpak(directory, verbose, allow_reinstall, allow_older, uninstall)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
args = parse_args()
|
||||
if 'extract' in args.command:
|
||||
if "extract" in args.command:
|
||||
if args.allow_reinstall:
|
||||
error(
|
||||
"allow-reinstall argument doesn't make sense with command %s"
|
||||
@ -358,7 +358,7 @@ if __name__ == '__main__':
|
||||
)
|
||||
if os.getuid() != 0:
|
||||
error("This tool must be run as root")
|
||||
with tempfile.TemporaryDirectory(prefix='fwupd') as target:
|
||||
with tempfile.TemporaryDirectory(prefix="fwupd") as target:
|
||||
unzip(target)
|
||||
run_installation(
|
||||
target,
|
||||
|
@ -28,12 +28,12 @@ def parse_args():
|
||||
)
|
||||
parser.add_argument(
|
||||
"--disable-snap-download",
|
||||
action='store_true',
|
||||
action="store_true",
|
||||
help="Don't download support for snap",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--disable-flatpak-download",
|
||||
action='store_true',
|
||||
action="store_true",
|
||||
help="Don't download support for flatpak",
|
||||
)
|
||||
parser.add_argument(
|
||||
@ -46,7 +46,7 @@ def parse_args():
|
||||
"cab",
|
||||
help="CAB file or directory containing CAB files to automatically install",
|
||||
)
|
||||
parser.add_argument('target', help='target file to create')
|
||||
parser.add_argument("target", help="target file to create")
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
@ -74,80 +74,80 @@ def generate_installer(directory, target):
|
||||
source = os.path.join(root, f)
|
||||
archive_fname = source.split(directory)[1]
|
||||
archive.write(source, archive_fname)
|
||||
if 'DEBUG' in os.environ:
|
||||
if "DEBUG" in os.environ:
|
||||
print(archive.namelist())
|
||||
archive.close()
|
||||
|
||||
with open(target, 'ab') as bytes_out:
|
||||
with open(target, "ab") as bytes_out:
|
||||
encoded = b64encode(buffer.getvalue())
|
||||
for section in bytes_slicer(64, encoded):
|
||||
bytes_out.write(TAG)
|
||||
bytes_out.write(section)
|
||||
bytes_out.write(b'\n')
|
||||
bytes_out.write(b"\n")
|
||||
|
||||
|
||||
def download_snap(directory, channel):
|
||||
cmd = ['snap', 'download', 'fwupd']
|
||||
cmd = ["snap", "download", "fwupd"]
|
||||
if channel is not None:
|
||||
cmd += ['--channel', channel]
|
||||
if 'DEBUG' in os.environ:
|
||||
cmd += ["--channel", channel]
|
||||
if "DEBUG" in os.environ:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, cwd=directory, check=True)
|
||||
for f in os.listdir(directory):
|
||||
# the signatures associated with the snap
|
||||
if f.endswith(".assert"):
|
||||
shutil.move(
|
||||
os.path.join(directory, f), os.path.join(directory, 'fwupd.assert')
|
||||
os.path.join(directory, f), os.path.join(directory, "fwupd.assert")
|
||||
)
|
||||
# the snap binary itself
|
||||
elif f.endswith(".snap"):
|
||||
shutil.move(
|
||||
os.path.join(directory, f), os.path.join(directory, 'fwupd.snap')
|
||||
os.path.join(directory, f), os.path.join(directory, "fwupd.snap")
|
||||
)
|
||||
|
||||
|
||||
def download_cab_file(directory, uri):
|
||||
cmd = ['wget', uri]
|
||||
if 'DEBUG' in os.environ:
|
||||
cmd = ["wget", uri]
|
||||
if "DEBUG" in os.environ:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, cwd=directory, check=True)
|
||||
|
||||
|
||||
def download_flatpak(directory):
|
||||
dep = 'org.freedesktop.fwupd'
|
||||
flatpak_dir = os.path.join(os.getenv('HOME'), '.local', 'share', 'flatpak')
|
||||
verbose = 'DEBUG' in os.environ
|
||||
dep = "org.freedesktop.fwupd"
|
||||
flatpak_dir = os.path.join(os.getenv("HOME"), ".local", "share", "flatpak")
|
||||
verbose = "DEBUG" in os.environ
|
||||
|
||||
# check if we have installed locally already or not
|
||||
if not os.path.exists(os.path.join(flatpak_dir, 'app', dep)):
|
||||
if not os.path.exists(os.path.join(flatpak_dir, "app", dep)):
|
||||
# install into local user's repo
|
||||
cmd = [
|
||||
'flatpak',
|
||||
'install',
|
||||
'--user',
|
||||
'https://www.flathub.org/repo/appstream/org.freedesktop.fwupd.flatpakref',
|
||||
'--no-deps',
|
||||
'-y',
|
||||
"flatpak",
|
||||
"install",
|
||||
"--user",
|
||||
"https://www.flathub.org/repo/appstream/org.freedesktop.fwupd.flatpakref",
|
||||
"--no-deps",
|
||||
"-y",
|
||||
]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, cwd=directory, check=True)
|
||||
|
||||
# generate a bundle
|
||||
repo = os.path.join(flatpak_dir, 'repo')
|
||||
cmd = ['flatpak', 'build-bundle', repo, 'fwupd.flatpak', dep, 'stable']
|
||||
repo = os.path.join(flatpak_dir, "repo")
|
||||
cmd = ["flatpak", "build-bundle", repo, "fwupd.flatpak", dep, "stable"]
|
||||
if verbose:
|
||||
print(cmd)
|
||||
subprocess.run(cmd, cwd=directory, check=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
args = parse_args()
|
||||
|
||||
if not args.cab.startswith("http"):
|
||||
local = args.cab
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix='fwupd') as directory:
|
||||
with tempfile.TemporaryDirectory(prefix="fwupd") as directory:
|
||||
if local:
|
||||
if not os.path.exists(local):
|
||||
error("%s doesn't exist" % local)
|
||||
|
@ -14,7 +14,7 @@ import glob
|
||||
import json
|
||||
from termcolor import colored
|
||||
|
||||
gi.require_version('Fwupd', '2.0')
|
||||
gi.require_version("Fwupd", "2.0")
|
||||
|
||||
from gi.repository import Fwupd
|
||||
from gi.repository import Gio
|
||||
@ -22,16 +22,16 @@ from gi.repository import GLib
|
||||
|
||||
|
||||
def _get_cache_file(fn):
|
||||
cachedir = os.path.expanduser('~/.cache/fwupdmgr')
|
||||
cachedir = os.path.expanduser("~/.cache/fwupdmgr")
|
||||
if not os.path.exists(cachedir):
|
||||
os.makedirs(cachedir)
|
||||
cachefn = os.path.join(cachedir, fn)
|
||||
if not os.path.exists(cachefn):
|
||||
url = 'https://fwupd.org/downloads/' + fn
|
||||
url = "https://fwupd.org/downloads/" + fn
|
||||
print("Downloading", url)
|
||||
r = requests.get(url)
|
||||
r.raise_for_status()
|
||||
f = open(cachefn, 'wb')
|
||||
f = open(cachefn, "wb")
|
||||
f.write(r.content)
|
||||
f.close()
|
||||
return cachefn
|
||||
@ -40,25 +40,25 @@ def _get_cache_file(fn):
|
||||
class DeviceTest:
|
||||
def __init__(self, obj):
|
||||
self.client = Fwupd.Client.new()
|
||||
self.name = obj.get('name', 'Unknown')
|
||||
self.guids = obj.get('guids', [])
|
||||
self.releases = obj.get('releases', [])
|
||||
self.has_runtime = obj.get('runtime', True)
|
||||
self.interactive = obj.get('interactive', False)
|
||||
self.disabled = obj.get('disabled', False)
|
||||
self.protocol = obj.get('protocol', None)
|
||||
self.name = obj.get("name", "Unknown")
|
||||
self.guids = obj.get("guids", [])
|
||||
self.releases = obj.get("releases", [])
|
||||
self.has_runtime = obj.get("runtime", True)
|
||||
self.interactive = obj.get("interactive", False)
|
||||
self.disabled = obj.get("disabled", False)
|
||||
self.protocol = obj.get("protocol", None)
|
||||
|
||||
def _info(self, msg):
|
||||
print(colored('[INFO]'.ljust(10), 'blue'), msg)
|
||||
print(colored("[INFO]".ljust(10), "blue"), msg)
|
||||
|
||||
def _warn(self, msg):
|
||||
print(colored('[WARN]'.ljust(10), 'yellow'), msg)
|
||||
print(colored("[WARN]".ljust(10), "yellow"), msg)
|
||||
|
||||
def _failed(self, msg):
|
||||
print(colored('[FAILED]'.ljust(10), 'red'), msg)
|
||||
print(colored("[FAILED]".ljust(10), "red"), msg)
|
||||
|
||||
def _success(self, msg):
|
||||
print(colored('[SUCCESS]'.ljust(10), 'green'), msg)
|
||||
print(colored("[SUCCESS]".ljust(10), "green"), msg)
|
||||
|
||||
def _get_by_device_guids(self):
|
||||
cancellable = Gio.Cancellable.new()
|
||||
@ -72,82 +72,82 @@ class DeviceTest:
|
||||
|
||||
def run(self):
|
||||
|
||||
print('Running test on {}'.format(self.name))
|
||||
print("Running test on {}".format(self.name))
|
||||
dev = self._get_by_device_guids()
|
||||
if not dev:
|
||||
self._warn('no {} attached'.format(self.name))
|
||||
self._warn("no {} attached".format(self.name))
|
||||
return
|
||||
|
||||
self._info('Current version {}'.format(dev.get_version()))
|
||||
self._info("Current version {}".format(dev.get_version()))
|
||||
|
||||
# apply each file
|
||||
for obj in self.releases:
|
||||
ver = obj.get('version')
|
||||
fn = obj.get('file')
|
||||
repeat = obj.get('repeat', 1)
|
||||
ver = obj.get("version")
|
||||
fn = obj.get("file")
|
||||
repeat = obj.get("repeat", 1)
|
||||
try:
|
||||
fn_cache = _get_cache_file(fn)
|
||||
except requests.exceptions.HTTPError as e:
|
||||
self._failed('Failed to download: {}'.format(str(e)))
|
||||
self._failed("Failed to download: {}".format(str(e)))
|
||||
return
|
||||
|
||||
# some hardware updates more than one partition with the same firmware
|
||||
for cnt in range(0, repeat):
|
||||
if dev.get_version() == ver:
|
||||
flags = Fwupd.InstallFlags.ALLOW_REINSTALL
|
||||
self._info('Reinstalling version {}'.format(ver))
|
||||
self._info("Reinstalling version {}".format(ver))
|
||||
else:
|
||||
flags = Fwupd.InstallFlags.ALLOW_OLDER
|
||||
self._info('Installing version {}'.format(ver))
|
||||
self._info("Installing version {}".format(ver))
|
||||
cancellable = Gio.Cancellable.new()
|
||||
|
||||
try:
|
||||
self.client.install(dev.get_id(), fn_cache, flags, cancellable)
|
||||
except GLib.Error as e:
|
||||
if str(e).find('no HWIDs matched') != -1:
|
||||
self._info('Skipping as {}'.format(e))
|
||||
if str(e).find("no HWIDs matched") != -1:
|
||||
self._info("Skipping as {}".format(e))
|
||||
continue
|
||||
self._failed('Could not install: {}'.format(e))
|
||||
self._failed("Could not install: {}".format(e))
|
||||
return
|
||||
|
||||
# verify version
|
||||
if self.has_runtime:
|
||||
dev = self._get_by_device_guids()
|
||||
if not dev:
|
||||
self._failed('Device did not come back: ' + self.name)
|
||||
self._failed("Device did not come back: " + self.name)
|
||||
return
|
||||
if not dev.get_version():
|
||||
self._failed('No version set after flash for: ' + self.name)
|
||||
self._failed("No version set after flash for: " + self.name)
|
||||
return
|
||||
if cnt == repeat - 1 and dev.get_version() != ver:
|
||||
self._failed('Got: ' + dev.get_version() + ', expected: ' + ver)
|
||||
self._failed("Got: " + dev.get_version() + ", expected: " + ver)
|
||||
return
|
||||
self._success('Installed {}'.format(dev.get_version()))
|
||||
self._success("Installed {}".format(dev.get_version()))
|
||||
else:
|
||||
self._success('Assumed success (no runtime)')
|
||||
self._success("Assumed success (no runtime)")
|
||||
|
||||
# wait for device to settle?
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
|
||||
# get manifests to parse
|
||||
device_fns = []
|
||||
if len(sys.argv) == 1:
|
||||
device_fns.extend(glob.glob('devices/*.json'))
|
||||
device_fns.extend(glob.glob("devices/*.json"))
|
||||
else:
|
||||
for fn in sys.argv[1:]:
|
||||
device_fns.append(fn)
|
||||
|
||||
# run each test
|
||||
for fn in sorted(device_fns):
|
||||
print('{}:'.format(fn))
|
||||
with open(fn, 'r') as f:
|
||||
print("{}:".format(fn))
|
||||
with open(fn, "r") as f:
|
||||
try:
|
||||
obj = json.load(f)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
print('Failed to parse {}: {}'.format(fn, e))
|
||||
print("Failed to parse {}: {}".format(fn, e))
|
||||
continue
|
||||
t = DeviceTest(obj)
|
||||
if t.disabled:
|
||||
|
@ -21,15 +21,15 @@ def usage(return_code):
|
||||
sys.exit(return_code)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if {'-?', '--help', '--usage'}.intersection(set(sys.argv)):
|
||||
if __name__ == "__main__":
|
||||
if {"-?", "--help", "--usage"}.intersection(set(sys.argv)):
|
||||
usage(0)
|
||||
if len(sys.argv) < 3:
|
||||
usage(1)
|
||||
m = hashlib.sha256()
|
||||
for argv in sys.argv[2:]:
|
||||
with open(argv, 'rb') as f:
|
||||
with open(argv, "rb") as f:
|
||||
m.update(f.read())
|
||||
with open(sys.argv[1], 'w') as f2:
|
||||
f2.write('#pragma once\n')
|
||||
with open(sys.argv[1], "w") as f2:
|
||||
f2.write("#pragma once\n")
|
||||
f2.write('#define FU_BUILD_HASH "%s"\n' % m.hexdigest())
|
||||
|
@ -13,26 +13,26 @@ from difflib import SequenceMatcher
|
||||
# finds a part using the ID
|
||||
def _find_part_by_id(parts, part_id):
|
||||
for part in parts:
|
||||
if 'id' not in part:
|
||||
if "id" not in part:
|
||||
continue
|
||||
if part['id'] == part_id:
|
||||
if part["id"] == part_id:
|
||||
return part
|
||||
return None
|
||||
|
||||
|
||||
# finds a memory layout for a part, climbing up the tree to the parent if reqd.
|
||||
def _find_mem_layout(parts, part):
|
||||
if 'memory-application' in part:
|
||||
memory_flash = part['memory-application']
|
||||
if "memory-application" in part:
|
||||
memory_flash = part["memory-application"]
|
||||
if memory_flash:
|
||||
return memory_flash
|
||||
|
||||
# look at the parent
|
||||
if 'parent' in part:
|
||||
parent = _find_part_by_id(parts, part['parent'])
|
||||
if "parent" in part:
|
||||
parent = _find_part_by_id(parts, part["parent"])
|
||||
if parent:
|
||||
return _find_mem_layout(parts, parent)
|
||||
print('no parent ', part['parent'], 'found for', part['id'])
|
||||
print("no parent ", part["parent"], "found for", part["id"])
|
||||
return None
|
||||
|
||||
|
||||
@ -47,8 +47,8 @@ def _parse_parts(fn_source):
|
||||
for line in open(fn_source).readlines():
|
||||
|
||||
# try to clean up crazy syntax
|
||||
line = line.replace('\n', '')
|
||||
if line.endswith(';'):
|
||||
line = line.replace("\n", "")
|
||||
if line.endswith(";"):
|
||||
line = line[:-1]
|
||||
|
||||
# ignore blank lines
|
||||
@ -59,42 +59,42 @@ def _parse_parts(fn_source):
|
||||
# count how many spaces deep this is
|
||||
lvl = 0
|
||||
for char in line:
|
||||
if char != ' ':
|
||||
if char != " ":
|
||||
break
|
||||
lvl = lvl + 1
|
||||
|
||||
# ignore comments
|
||||
line = line.strip()
|
||||
if line[0] == '#':
|
||||
if line[0] == "#":
|
||||
continue
|
||||
|
||||
# level 0 of hell
|
||||
if lvl == 0:
|
||||
if line.startswith('part'):
|
||||
if line.startswith("part"):
|
||||
memory_id = None
|
||||
part = {}
|
||||
parts.append(part)
|
||||
if line.startswith('part parent '):
|
||||
part['parent'] = line[13:].replace('"', '')
|
||||
if line.startswith("part parent "):
|
||||
part["parent"] = line[13:].replace('"', "")
|
||||
continue
|
||||
|
||||
# level 4 of hell
|
||||
if lvl == 4:
|
||||
if line.startswith('memory'):
|
||||
memory_id = 'memory-' + line[7:].replace('"', '')
|
||||
if line.startswith("memory"):
|
||||
memory_id = "memory-" + line[7:].replace('"', "")
|
||||
part[memory_id] = {}
|
||||
continue
|
||||
split = line.split('=')
|
||||
split = line.split("=")
|
||||
if len(split) != 2:
|
||||
print('ignoring', line)
|
||||
print("ignoring", line)
|
||||
continue
|
||||
part[split[0].strip()] = split[1].strip().replace('"', '')
|
||||
part[split[0].strip()] = split[1].strip().replace('"', "")
|
||||
continue
|
||||
|
||||
# level 8 of hell
|
||||
if lvl == 8:
|
||||
if memory_id:
|
||||
split = line.split('=')
|
||||
split = line.split("=")
|
||||
if len(split) != 2:
|
||||
continue
|
||||
memory = part[memory_id]
|
||||
@ -117,52 +117,52 @@ def _write_quirks(parts, fn_destination):
|
||||
for part in parts:
|
||||
|
||||
# ignore meta parts with deprecated names
|
||||
if 'desc' not in part:
|
||||
if "desc" not in part:
|
||||
continue
|
||||
if 'signature' not in part:
|
||||
if "signature" not in part:
|
||||
continue
|
||||
|
||||
# find the layout
|
||||
mem_part = _find_mem_layout(parts, part)
|
||||
if not mem_part:
|
||||
print("no memory layout for", part['desc'])
|
||||
print("no memory layout for", part["desc"])
|
||||
continue
|
||||
if not 'size' in mem_part:
|
||||
print("no memory size for", part['desc'])
|
||||
if not "size" in mem_part:
|
||||
print("no memory size for", part["desc"])
|
||||
continue
|
||||
if mem_part['size'].startswith('0x'):
|
||||
size = int(mem_part['size'], 16)
|
||||
if mem_part["size"].startswith("0x"):
|
||||
size = int(mem_part["size"], 16)
|
||||
else:
|
||||
size = int(mem_part['size'], 10)
|
||||
size = int(mem_part["size"], 10)
|
||||
|
||||
# output the line for the quirk
|
||||
chip_id = '0x' + part['signature'].replace('0x', '').replace(' ', '')
|
||||
mem_layout = '@Flash/0x0/1*%.0iKg' % int(size / 1024)
|
||||
chip_id = "0x" + part["signature"].replace("0x", "").replace(" ", "")
|
||||
mem_layout = "@Flash/0x0/1*%.0iKg" % int(size / 1024)
|
||||
|
||||
# merge duplicate quirks
|
||||
if chip_id in results:
|
||||
result = results[chip_id]
|
||||
result['desc'] = _get_longest_substring(result['desc'], part['desc'])
|
||||
result["desc"] = _get_longest_substring(result["desc"], part["desc"])
|
||||
else:
|
||||
result = {}
|
||||
result['desc'] = part['desc']
|
||||
result['size'] = size
|
||||
result['mem_layout'] = mem_layout
|
||||
result["desc"] = part["desc"]
|
||||
result["size"] = size
|
||||
result["mem_layout"] = mem_layout
|
||||
results[chip_id] = result
|
||||
|
||||
for chip_id in results:
|
||||
result = results[chip_id]
|
||||
outp.append(
|
||||
'# ' + result['desc'] + ' [USER] USER=0x%x' % result['size'] + '\n'
|
||||
"# " + result["desc"] + " [USER] USER=0x%x" % result["size"] + "\n"
|
||||
)
|
||||
outp.append(chip_id + '=' + result['mem_layout'] + '\n\n')
|
||||
outp.append(chip_id + "=" + result["mem_layout"] + "\n\n")
|
||||
|
||||
# write file
|
||||
print("writing", fn_destination)
|
||||
open(fn_destination, 'w').writelines(outp)
|
||||
open(fn_destination, "w").writelines(outp)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 3:
|
||||
print("USAGE: %s avrdude.conf tmp.quirk" % sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
@ -50,15 +50,7 @@ def _run_objcopy(args):
|
||||
def _run_genpeimg(args):
|
||||
|
||||
# this is okay if it does not exist
|
||||
argv = [
|
||||
"genpeimg",
|
||||
"-d",
|
||||
"+d",
|
||||
"+n",
|
||||
"-d",
|
||||
"+s",
|
||||
args.outfile,
|
||||
]
|
||||
argv = ["genpeimg", "-d", "+d", "+n", "-d", "+s", args.outfile]
|
||||
try:
|
||||
subprocess.run(argv, check=True)
|
||||
except FileNotFoundError as _:
|
||||
@ -69,23 +61,11 @@ if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--objcopy",
|
||||
default="objcopy",
|
||||
help="Binary file to use for objcopy",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--arch",
|
||||
default="x86_64",
|
||||
help="EFI architecture",
|
||||
)
|
||||
parser.add_argument(
|
||||
"infile",
|
||||
help="Input file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"outfile",
|
||||
help="Output file",
|
||||
"--objcopy", default="objcopy", help="Binary file to use for objcopy"
|
||||
)
|
||||
parser.add_argument("--arch", default="x86_64", help="EFI architecture")
|
||||
parser.add_argument("infile", help="Input file")
|
||||
parser.add_argument("outfile", help="Output file")
|
||||
_args = parser.parse_args()
|
||||
_run_objcopy(_args)
|
||||
_run_genpeimg(_args)
|
||||
|
@ -81,40 +81,18 @@ if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--cc",
|
||||
default="gcc",
|
||||
help="Compiler to use for generating sbat object",
|
||||
"--cc", default="gcc", help="Compiler to use for generating sbat object"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--objcopy",
|
||||
default="objcopy",
|
||||
help="Binary file to use for objcopy",
|
||||
"--objcopy", default="objcopy", help="Binary file to use for objcopy"
|
||||
)
|
||||
parser.add_argument("--project-name", help="SBAT project name")
|
||||
parser.add_argument("--project-version", help="SBAT project version")
|
||||
parser.add_argument("--sbat-version", default=1, type=int, help="SBAT version")
|
||||
parser.add_argument(
|
||||
"--project-name",
|
||||
help="SBAT project name",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--project-version",
|
||||
help="SBAT project version",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sbat-version",
|
||||
default=1,
|
||||
type=int,
|
||||
help="SBAT version",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sbat-generation",
|
||||
default=1,
|
||||
type=int,
|
||||
help="SBAT generation",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sbat-distro-id",
|
||||
default=None,
|
||||
help="SBAT distribution ID"
|
||||
"--sbat-generation", default=1, type=int, help="SBAT generation"
|
||||
)
|
||||
parser.add_argument("--sbat-distro-id", default=None, help="SBAT distribution ID")
|
||||
parser.add_argument(
|
||||
"--sbat-distro-generation",
|
||||
default=None,
|
||||
@ -122,29 +100,16 @@ if __name__ == "__main__":
|
||||
help="SBAT distribution generation",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sbat-distro-summary",
|
||||
default=None,
|
||||
help="SBAT distribution summary",
|
||||
"--sbat-distro-summary", default=None, help="SBAT distribution summary"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sbat-distro-pkgname",
|
||||
default=None,
|
||||
help="SBAT distribution package name",
|
||||
"--sbat-distro-pkgname", default=None, help="SBAT distribution package name"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sbat-distro-version",
|
||||
default=None,
|
||||
help="SBAT distribution version",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sbat-distro-url",
|
||||
default=None,
|
||||
help="SBAT distribution URL",
|
||||
)
|
||||
parser.add_argument(
|
||||
"outfile",
|
||||
help="Output file",
|
||||
"--sbat-distro-version", default=None, help="SBAT distribution version"
|
||||
)
|
||||
parser.add_argument("--sbat-distro-url", default=None, help="SBAT distribution URL")
|
||||
parser.add_argument("outfile", help="Output file")
|
||||
_args = parser.parse_args()
|
||||
_generate_sbat(_args)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user