diff --git a/.gitignore b/.gitignore index b05ae27..73fc79c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode/ -venv/ \ No newline at end of file +venv/ +secrets/ diff --git a/arch/base.md b/arch/base.md index 05a701d..79f51fd 100644 --- a/arch/base.md +++ b/arch/base.md @@ -55,6 +55,8 @@ I have instructions for building a: - [CUPS Printing](#cups-printing) - [Yubikey](#yubikey) - [Bashrc](#bashrc) + - [Colorized Prompt](#colorized-prompt) + - [Standard Bashrc](#standard-bashrc) ## Installation @@ -899,6 +901,12 @@ systemctl enable --now iscsid # Log out of all sessions iscsiadm -m node -u + + # Log out of a single session + iscsiadm -m node -T iqn.2023-01.driveripper.reeselink.com:2024-01-framework --logout + + # Remove session + iscsiadm -m node -o delete -T iqn.2023-01.driveripper.reeselink.com:2023-01-framework ``` ## Software Stores @@ -1001,6 +1009,20 @@ sudo systemctl enable --now pcscd ## Bashrc +### Colorized Prompt + + + +You can change the prompt color by setting PROMPT_COLOR at the top of your .bashrc + +Examples: + +Yellow: `PROMPT_COLOR=33;` +Orange: `PROMPT_COLOR=38;5;208;` +Red: `PROMPT_COLOR=38;5;160;` + +### Standard Bashrc + Don't do this if you installed `zsh` ~/.bashrc diff --git a/arch/gaming.md b/arch/gaming.md index 8153ee3..60d159c 100644 --- a/arch/gaming.md +++ b/arch/gaming.md @@ -167,6 +167,11 @@ network streaming to any device that can run moonlight. I used the Archlinux pkg. Follow the instructions (including the autostart instructions). +```bash +wget https://github.com/LizardByte/Sunshine/releases/latest/download/sunshine.pkg.tar.zst +pacman -U --noconfirm sunshine.pkg.tar.zst +``` + ### Install Moonlight diff --git a/arch/workstation.md b/arch/workstation.md index 9fa0750..1715ac8 100644 --- a/arch/workstation.md +++ b/arch/workstation.md @@ -2,10 +2,12 @@ - [Workstation](#workstation) - [Framework AMD Notes](#framework-amd-notes) - - [Wifi](#wifi) + - [ATH12K Wifi Drivers](#ath12k-wifi-drivers) - [Microcode](#microcode) + - [linux-git kernel](#linux-git-kernel) - [Base Tools](#base-tools) - [ZSH](#zsh) + - [Prompt Themes](#prompt-themes) - [Aliases](#aliases) - [Rollback Pacman Update](#rollback-pacman-update) - [Podman](#podman) @@ -31,6 +33,7 @@ - [Initialization](#initialization) - [Development](#development) - [Cura](#cura) + - [Creality Print](#creality-print) - [AWS CLI](#aws-cli) - [NSlookup](#nslookup) - [rpi-imager](#rpi-imager) @@ -40,7 +43,7 @@ ## Framework AMD Notes -### Wifi +### ATH12K Wifi Drivers Install the wireless-regdb to set the regulatory domain to US @@ -50,20 +53,21 @@ pacman -S wireless-regdb Edit `/etc/conf.d/wireless-regdom` to set the domain -Switch to iwd for the NetworkManager backend. + -```bash -pacman -S iwd -``` +1. `git clone https://git.codelinaro.org/clo/ath-firmware/ath12k-firmware` +2. `cd ath12k-firmware` +3. Run the following: -Edit `/etc/NetworkManager/conf.d/wifi_backend.conf` + ```bash + wget https://github.com/qca/qca-swiss-army-knife/raw/master/tools/scripts/ath12k/ath12k-fw-repo + chmod 755 ath12k-fw-repo + sudo ./ath12k-fw-repo --install /lib/firmware + ``` -```conf -[device] -wifi.backend=iwd -``` - -Finally, reboot the machine for the changes to take effect. +4. `sudo cp ath12k/board.bin /lib/firmware/ath12k/WCN7850/hw2.0/` +5. `sudo cp ath12k/regdb.bin /lib/firmware/ath12k/WCN7850/hw2.0/` +6. Reboot ### Microcode @@ -81,10 +85,20 @@ initrd /initramfs-linux.img options ... ``` +### linux-git kernel + + + +1. `git clone https://aur.archlinux.org/linux-git.git` +2. `cd linux-git` +3. `makepkg` +4. `sudo pacman -U linux-git... linux-git-headers...` + ## Base Tools ```bash -pacman -S rsync which git iperf3 pwgen dosfstools exfatprogs +# gvfs and gvfs-dnssd are for webdav support +pacman -S rsync which git iperf3 pwgen dosfstools exfatprogs gvfs gvfs-dnssd ``` ## ZSH @@ -92,7 +106,43 @@ pacman -S rsync which git iperf3 pwgen dosfstools exfatprogs ```bash pacman -S zsh grml-zsh-config chsh -s $(which zsh) -echo "autoload -U compinit; compinit" > ~/.zshrc + +cat < ~/.zshrc +# Basic settings +autoload bashcompinit && bashcompinit +autoload -U compinit; compinit +zstyle ':completion:*' menu select + +# Prompt settings +autoload -Uz promptinit +promptinit +PROMPT_EOL_MARK= + +# Syntax Highlighting +source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh +source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh + +# Command Not Found Autocomplete +source /usr/share/doc/pkgfile/command-not-found.zsh + +### Custom Commands and Aliases ### +EOF +``` + +### Prompt Themes + +See: + +Use `prompt -l` to list prompts + +Use `prompt -p` to see previews + +In your `.zshrc` set the following: + +```bash +autoload -Uz promptinit +promptinit +prompt grml ``` ### Aliases @@ -444,6 +494,23 @@ Icon=/home/ducoterra/.icons/cura.png Type=Application ``` +## Creality Print + + + +```bash +mv ~/Downloads/Creality_Print*.AppImage ~/Applications/Creality_Print.AppImage +chmod +x ~/Applications/*.AppImage +``` + +```conf +[Desktop Entry] +Name=Creality Print +Exec=/home/ducoterra/Applications/Creality_Print.AppImage +Icon=/home/ducoterra/.icons/creality_print.png +Type=Application +``` + ## AWS CLI diff --git a/ath12k/ath12k-fw-repo b/ath12k/ath12k-fw-repo new file mode 100755 index 0000000..edec54c --- /dev/null +++ b/ath12k/ath12k-fw-repo @@ -0,0 +1,1032 @@ +#!/usr/bin/python3 +# +# Copyright (c) 2016 Qualcomm Atheros, Inc. +# Copyright (c) 2018,2020 The Linux Foundation. All rights reserved. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import os +import logging +import re +import argparse +import shutil +import sys +import filecmp +import functools +import subprocess +import email + +# global variables +logger = None + +BRANCH_DEFAULT_PRIORITY = 1000 +BRANCH_PRIORITY_FILE = '.priority' +WHENCE_FILE = 'WHENCE' +NOTICE_FILE = 'Notice.txt' +NOTICE_FILE_LEN_MIN = 5000 +ATH12K_DIR = 'ath12k' +TESTING_BRANCH = 'testing' + +FIRMWARE_BLACKLIST = [ +] + +BRANCH_BLACKLIST = [ + 'msm', +] + + +@functools.total_ordering +class Hardware(): + def get_path(self): + return os.path.join(self.hw, self.hw_ver) + + def __eq__(self, other): + return self.name == other.name + + def __lt__(self, other): + return self.name < other.name + + def __repr__(self): + return self.__str__() + + def __str__(self): + return 'Hardware(\'%s\'): %s %s' % (self.name, self.board_files, + sorted(self.firmware_branches)) + + def __init__(self, hw, hw_ver): + # QCA6174 + self.hw = hw + + # hw3.0 + self.hw_ver = hw_ver + + self.name = '%s %s' % (hw, hw_ver) + + self.firmware_branches = [] + self.board_files = [] + + +@functools.total_ordering +class FirmwareBranch(): + # return the branch name without 'testing/' prefix + def get_clean_name(self): + if self.testing_branch: + return self.name[len(TESTING_BRANCH):] + + return self.name + + def __eq__(self, other): + return self.priority == other.priority and \ + self.get_clean_name() == other.get_clean_name() + + def __lt__(self, other): + # '.' is always of the lower priority + if self.name == '.': + return True + + if other.name == '.': + return False + + if self.priority != other.priority: + if self.priority < other.priority: + return True + else: + return False + + return self.get_clean_name() < other.get_clean_name() + + def __repr__(self): + return self.__str__() + + def __str__(self): + return 'FirmwareBranch(\'%s\'): %s' % (self.name, sorted(self.firmwares)) + + def __init__(self, name, path=None): + self.name = name + self.firmwares = [] + + if name.startswith(TESTING_BRANCH): + self.testing_branch = True + + # testing branches use lower priority by default so that + # they are ordered below normal branches + self.priority = 0 + else: + self.testing_branch = False + self.priority = BRANCH_DEFAULT_PRIORITY + + if path: + priority_path = os.path.join(path, BRANCH_PRIORITY_FILE) + if os.path.isfile(priority_path): + try: + f = open(priority_path, 'r') + buf = f.read() + f.close() + + self.priority = int(buf) + except Exception as e: + logger.error('Failed to read %s: %s' % (priority_path, e)) + + +class BoardFile(): + + @staticmethod + def create_from_path(path): + filename = os.path.basename(path) + + match = re.search(r'^board-(\d+).bin', filename) + if match is None: + match = re.search(r'^board.bin', filename) + if match is None: + return None + + if len(match.groups()) > 1: + bd_api = match.group(1) + else: + bd_api = None + + return BoardFile(path, bd_api) + + def get_basename(self): + return os.path.basename(self.path) + + def __repr__(self): + return self.__str__() + + def __str__(self): + return '%s' % (self.get_basename()) + + def __init__(self, path, bd_api): + # full path to the board file, including directories and filename + self.path = path + + # board api version, eg. '2' in board-2.bin + self.bd_api = bd_api + + +class Firmware(): + + @staticmethod + def create_from_path(path): + if not os.path.isdir(path): + raise Exception('Firmware path %s is not a directory') + + fw_ver = os.path.basename(path) + + return Firmware(fw_ver, path) + + def get_files_with_path(self): + result = [] + + for filename in self.filenames: + result.append(os.path.join(self.path, filename)) + return result + + def get_notice_path(self): + return os.path.join(self.path, self.notice_filename) + + def __eq__(self, other): + return self.fw_ver == other.fw_ver + + def __ne__(self, other): + return not self.__eq__(other) + + # FIXME: firmware-5.bin_10.4-3.2-00080 and + # firmware-5.bin_10.4-3.2.1-00028 are sorted incorrectly + def __lt__(self, other): + s = self.fw_ver + o = other.fw_ver + + # FIXME: An ugly hack that to make the comparison easier to + # implement. Just to get some sort of simple sorting working + # replace '-' with '.' in version string. But now for example + # '10.2.4.70.2 > 10.2.4.70-2' is not compared correctly. + + s = s.replace('-', '.') + o = o.replace('-', '.') + + s = s.split('.') + o = o.split('.') + + s2 = s + o2 = o + + s = [] + o = [] + + for t in s2: + try: + k = int(t) + except: + k = t + + s.append(k) + + for t in o2: + try: + k = int(t) + except: + k = t + + o.append(k) + + l = min(len(s), len(o)) + + for i in range(l): + + if s[i] < o[i]: + return True + elif s[i] > o[i]: + return False + + if len(s) > len(o): + return False + + return True + + def __le__(self, other): + return self.__lt__(other) or self.__eq__(other) + + def __gt__(self, other): + return not self.__le__(other) + + def __ge__(self, other): + return self.__gt__(other) or self.__eq__(other) + + def __repr__(self): + return self.__str__() + + def __str__(self): + return '%s' % (self.fw_ver) + + # path can be None with unittests + def __init__(self, fw_ver, path=None): + # path to the release directory, no filenames + self.path = path + + # filenames of all firmware files, excluding notice file + self.filenames = [] + + # filename of the notice file, excluding path + self.notice_filename = None + + # firmware version + self.fw_ver = fw_ver + + if path: + files = os.listdir(path) + files.sort() + + for filename in files: + if filename == NOTICE_FILE: + logger.debug('%s: %s' % (self.fw_ver, filename)) + self.notice_filename = filename + continue + + self.filenames.append(filename) + + logger.debug('%s: %s' % (self.fw_ver, self.filenames)) + + # check notice file + if self.notice_filename is None: + print('%s: missing %s' % (self.path, NOTICE_FILE)) + return + + notice_path = os.path.join(self.path, self.notice_filename) + f = open(notice_path, 'r') + try: + buf = f.read() + except UnicodeDecodeError as e: + print('%s: invalid utf-8: %s' % (notice_path, e)) + self.notice_filename = None + return + finally: + f.close() + + if len(buf) < NOTICE_FILE_LEN_MIN: + print('%s: too short: %d B' % (notice_path, len(buf))) + self.notice_filename = None + return + + +def scan_branch_dir(path): + fw_list = [] + + files = os.listdir(path) + files.sort() + + for f in files: + f_path = os.path.join(path, f) + + if not os.path.isdir(f_path): + continue + + firmware = Firmware.create_from_path(f_path) + if firmware: + if firmware.fw_ver in FIRMWARE_BLACKLIST: + logger.debug('Blacklisted firmware release: %s' % (firmware.fw_ver)) + continue + + logger.debug('Found firmware release: %s' % (firmware.fw_ver)) + fw_list.append(firmware) + continue + + logger.warning('Unknown file: %s' % (f_path)) + + return fw_list + + +# QCA988X/hw2.0 +def scan_hw_ver(hw): + path = hw.get_path() + files = os.listdir(path) + files.sort() + + for fw_branch in files: + if fw_branch == TESTING_BRANCH: + # scan all directories under testing branch, eg. testing/1.2.3.4 + dirs = os.listdir(os.path.join(path, fw_branch)) + fw_branches = [] + for d in dirs: + fw_branches.append(os.path.join(TESTING_BRANCH, d)) + else: + fw_branches = [fw_branch] + + for fw_branch in fw_branches: + fw_branch_path = os.path.join(path, fw_branch) + + if not os.path.isdir(fw_branch_path): + continue + + if os.path.basename(fw_branch_path) in BRANCH_BLACKLIST: + logger.debug('Blacklisted firmware branch: %s' % (fw_branch_path)) + continue + + logger.debug('Found firmware branch: %s' % (fw_branch)) + fb = FirmwareBranch(fw_branch, fw_branch_path) + hw.firmware_branches.append(fb) + + fw = scan_branch_dir(fw_branch_path) + fb.firmwares += fw + + files = os.listdir(path) + for f_path in files: + boardfile = BoardFile.create_from_path(os.path.join(path, f_path)) + if boardfile: + logger.debug('Found board file: %s' % (f_path)) + hw.board_files.append(boardfile) + continue + + +# QCA98XX +def scan_hw(path): + hws = [] + + files = os.listdir(path) + files.sort() + + for hw_ver in files: + hw_ver_path = os.path.join(path, hw_ver) + + if not os.path.isdir(hw_ver_path): + continue + + # skip symbolic links, for example WCN6855 hw2.1 + if os.path.islink(hw_ver_path): + continue + + logger.debug('Found hw version: %s' % (hw_ver)) + + hw = Hardware(path, hw_ver) + scan_hw_ver(hw) + + if len(hw.firmware_branches) == 0: + logger.debug('Skipping due to no firmware branches found: %s' % (hw.name)) + continue + + hws.append(hw) + + return hws + + +def scan_repository(directory): + hws = {} + + files = os.listdir(directory) + files.sort() + + for hw_name in files: + if not os.path.isdir(hw_name): + continue + + # skip hidden directories + if hw_name.startswith('.'): + continue + + logger.debug('Found hw: %s' % (hw_name)) + + hw_list = scan_hw(hw_name) + + for hw in hw_list: + hws[hw.name] = hw + + return hws + + +# srcpath: full pathname (directory + filename) where copy from +def install_file(args, srcpath, destdir, destfilename): + logger.debug('install_file(%s, %s, %s)' % (srcpath, destdir, destfilename)) + + if args.dry_run: + return + + destpath = os.path.join(destdir, destfilename) + + destdir = os.path.dirname(destpath) + if not os.path.isdir(destdir): + os.makedirs(destdir) + + logger.info('\t%s -> %s' % (srcpath, destpath)) + shutil.copyfile(srcpath, destpath) + + return destpath + + +def get_firmware_version(path): + cmd = ['ath12k-fwencoder', '--info', path] + info = subprocess.check_output(cmd, universal_newlines=True) + msg = email.message_from_string(info) + return msg['FirmwareVersion'] + + +def get_board_crc32(path): + cmd = ['ath12k-fwencoder', '--crc32', path] + return subprocess.check_output(cmd, universal_newlines=True).strip() + + +# print indent +def pi(level, msg): + print('%s%s' % (level * '\t', msg)) + + +# The WHENCE file update is implemented by using board-2.bin entry as +# an "anchor". All entries (including File, Version and License) for +# that hardware directory will be replaces by the new ones. As the +# filepaths is always sorted the changes visible in git-diff will be +# actually changed files. +# +# Only called during firmware updates. Board file updates don't need +# changes in WHENCE and that's why this function doesn't support board +# file changes. +def whence_update(linux_firmware, filepaths, version): + whencepath = os.path.join(linux_firmware, WHENCE_FILE) + license_relpath = None + + if not os.path.exists(whencepath): + return None + + f = open(whencepath, 'r') + buf = f.read() + f.close() + + dirname = os.path.dirname(os.path.relpath(filepaths[0], linux_firmware)) + + pattern = r'(File: %s/board-\d+.bin\n)(.*%s.*?\n)+' % (dirname, + dirname) + + # \g<1> is same as \1 but needed to separate from the version string + replace = r'\g<1>' + + for filepath in filepaths: + relpath = os.path.relpath(filepath, linux_firmware) + if relpath.endswith(NOTICE_FILE): + license_relpath = relpath + continue + + replace += r'File: %s\n' % (relpath) + + if version is not None: + replace += r'Version: %s\n' % (version) + + # license (or notice.txt to be exact) needs to be last + if license_relpath is not None: + replace += r'File: %s\n' % (license_relpath) + + (buf, sub_count) = re.subn(pattern, replace, buf, + flags=re.MULTILINE | re.DOTALL) + + if sub_count != 1: + logger.error('Failed to add %s to WHENCE: %d' % (version, sub_count)) + return None + + f = open(whencepath, 'w') + f.write(buf) + f.close() + + return whencepath + + +def whence_add(linux_firmware, filepaths, version=None): + whencepath = os.path.join(linux_firmware, WHENCE_FILE) + license_relpath = None + + if not os.path.exists(whencepath): + return None + + f = open(whencepath, 'r') + buf = f.read() + f.close() + + pattern = r'(Driver: ath12k.*?\n\n.*?)\n\n' + + # \g<1> is same as \1 but needed to separate from the version string + replace = r'\g<1>\n' + + for filepath in filepaths: + relpath = os.path.relpath(filepath, linux_firmware) + if relpath.endswith(NOTICE_FILE): + license_relpath = relpath + continue + + replace += r'File: %s\n' % (relpath) + + if version is not None: + replace += r'Version: %s\n' % (version) + + # license (or notice.txt to be exact) needs to be last + if license_relpath is not None: + replace += r'File: %s\n' % (license_relpath) + + # empty line before the 'Licence: Redistributable.' line + replace += r'\n' + + (buf, sub_count) = re.subn(pattern, replace, buf, + flags=re.MULTILINE | re.DOTALL) + + if sub_count != 1: + logger.error('Failed to add %s to WHENCE: %d' % (version, sub_count)) + return None + + f = open(whencepath, 'w') + f.write(buf) + f.close() + + return whencepath + + +def git_commit(args, msg, repodir, files): + if not args.commit: + # nothing to do + return + + cmd = ['git', '-C', repodir, 'commit', '--quiet', '--signoff', '-m', msg] + files + + logger.debug('Running: %r' % (cmd)) + subprocess.check_call(cmd) + + +def git_add(args, repodir, files): + if not args.commit: + # nothing to do + return + + cmd = ['git', '-C', repodir, 'add'] + files + + logger.debug('Running: %r' % (cmd)) + subprocess.check_call(cmd) + + +def git_rm(args, repodir, files): + if not args.commit: + # nothing to do + return + + cmd = ['git', '-C', repodir, 'rm', '--quiet'] + files + + logger.debug('Running: %r' % (cmd)) + subprocess.check_call(cmd) + + +def cmd_check(args): + scan_repository('.') + + +def cmd_list(args): + level = 0 + + hws = scan_repository('.') + for hw in sorted(hws.values()): + pi(level, '%s:' % (hw.name)) + level += 1 + + # print board files + if len(hw.board_files) > 0: + pi(level, 'board') + level += 1 + + for board_file in sorted(hw.board_files): + pi(level, board_file) + + level -= 1 + + # print firmware branches + for branch in sorted(hw.firmware_branches): + if len(branch.firmwares) == 0: + # don't print empty branches + continue + + pi(level, '%s' % (branch.name)) + level += 1 + + for fw in sorted(branch.firmwares): + pi(level, fw.fw_ver) + + level -= 1 + + level -= 1 + + +def cmd_list_hardware(args): + hws = scan_repository('.') + for hw in sorted(hws.values()): + print(hw.name) + + +def cmd_list_branches(args): + hw_name = args.list_branches[0] + hw_ver = args.list_branches[1] + + hws = scan_repository('.') + for hw in sorted(hws.values()): + if hw.name == '%s %s' % (hw_name, hw_ver): + for branch in sorted(hw.firmware_branches): + print(branch.name) + + return + + +def cmd_list_releases(args): + hw_name = args.list_releases[0] + hw_ver = args.list_releases[1] + fw_branch = args.list_releases[2] + + hws = scan_repository('.') + for hw in sorted(hws.values()): + if hw.name == '%s %s' % (hw_name, hw_ver): + for branch in sorted(hw.firmware_branches): + if fw_branch == branch.name: + for fw in branch.firmwares: + print(fw.fw_ver) + + return + + +def cmd_list_lib_dir(args): + fw_dir = args.list_lib_dir[0] + ath12k_dir = os.path.join(fw_dir, ATH12K_DIR) + + if not os.path.exists(ath12k_dir): + logger.error('directory %s does not exist, aborting' % (ath12k_dir)) + sys.exit(1) + + if not os.path.isdir(ath12k_dir): + logger.error('%s is not a directory, aborting' % (ath12k_dir)) + sys.exit(1) + + # sort the results based on dirpath + for (dirpath, dirnames, filenames) in sorted(os.walk(ath12k_dir)): + found = [] + for filename in sorted(filenames): + path = os.path.join(dirpath, filename) + + match = re.match(r'firmware.*\.bin', filename) + if match is not None: + # this is a firmware file + s = '%s\t%s' % (filename, get_firmware_version(path)) + found.append(s) + + match = re.match(r'board.*\.bin', filename) + if match is not None: + # this is a board file + s = '%s\t%s' % (filename, get_board_crc32(path)) + found.append(s) + + if len(found) > 0: + # Just show QCA1234/hw1.0 directories. I would have liked + # to use os.path functions here but just could not find + # anything sensible there. + pi(0, '%s:' % ('/'.join(dirpath.split('/')[-2:]))) + for line in found: + pi(1, line) + + +def cmd_get_latest_in_branch(args): + # As this command is mostly for scripts to parse, don't show + # warnings etc to clutter the output, unless we are debugging of + # course. + if not args.debug: + logger.setLevel(logging.ERROR) + + hws = scan_repository('.') + + args_hw = args.get_latest_in_branch[0] + args_hwver = args.get_latest_in_branch[1] + args_fwbranch = args.get_latest_in_branch[2] + + # TODO: hw is always in uppercase and hwver lower case, check that + hw_name = '%s %s' % (args_hw, args_hwver) + + if hw_name not in hws: + logger.error('Did not find hardware: %s' % (hw_name)) + sys.exit(1) + + hw = hws[hw_name] + + fw_branch = None + + for b in hw.firmware_branches: + if b.name == args_fwbranch: + fw_branch = b + break + + if fw_branch is None: + logger.error('Did not find firmware branch: %s' % (args_fwbranch)) + sys.exit(1) + + if len(fw_branch.firmwares) == 0: + # no firmware images in this branch, just use return value 0 with no output + sys.exit(0) + + print(sorted(fw_branch.firmwares)[-1].path) + + sys.exit(0) + + +def cmd_get_latest_in_hw(args): + # As this command is mostly for scripts to parse, don't show + # warnings etc to clutter the output, unless we are debugging of + # course. + if not args.debug: + logger.setLevel(logging.ERROR) + + hws = scan_repository('.') + + args_hw = args.get_latest[0] + args_hwver = args.get_latest[1] + + # TODO: hw is always in uppercase and hwver lower case, check that + hw_name = '%s %s' % (args_hw, args_hwver) + + if hw_name not in hws: + logger.error('Did not find hardware: %s' % (hw_name)) + sys.exit(1) + + hw = hws[hw_name] + + for branch in sorted(hw.firmware_branches, reverse=True): + if len(branch.firmwares) == 0: + # ignore an empty branch + continue + + print(sorted(branch.firmwares)[-1].path) + break + + sys.exit(0) + + +def cmd_install(args): + hws = scan_repository('.') + + linux_firmware = args.install[0] + ath12kdir = os.path.join(linux_firmware, ATH12K_DIR) + + if not os.path.exists(ath12kdir): + os.makedirs(ath12kdir) + + if not os.path.isdir(ath12kdir): + logger.error('%s is not a directory' % (ath12kdir)) + sys.exit(1) + + logger.debug('Installing to directory %s' % (ath12kdir)) + + for hw in sorted(hws.values()): + bd_list = hw.board_files + + # every Hardware() should have at least one firmware branch, the + # main '.' branch so no need to check the length + fw_list = sorted(sorted(hw.firmware_branches)[-1].firmwares) + + if len(fw_list) == 0: + logger.debug('no firmware images found for %s' % (hw)) + continue + + destdir = os.path.join(ath12kdir, hw.get_path()) + + # install board files first as that's used as an "anchor" for + # firmware files WHENCE updates + for bd in bd_list: + installed = [] + dest = os.path.join(ath12kdir, bd.path) + if not os.path.exists(dest) or not filecmp.cmp(bd.path, dest): + if os.path.exists(dest): + action = 'update' + else: + action = 'add' + + logger.info('Installing board file %s' % (bd.path)) + destpath = install_file(args, bd.path, destdir, + bd.get_basename()) + installed.append(destpath) + + if action == 'add': + whencepath = whence_add(linux_firmware, installed) + if whencepath is not None: + installed.append(whencepath) + + git_add(args, linux_firmware, installed) + + msg = 'ath12k: %s: %s %s' % (hw.name, + action, + bd.get_basename()) + git_commit(args, msg, linux_firmware, installed) + else: + logger.debug('No update needed for %s' % (bd.path)) + + # install latest firmware + fw = fw_list[-1] + + to_add = [] + to_update = [] + to_remove = [] + + # remove notice and board files from to_remove + if os.path.exists(destdir): + for filename in os.listdir(destdir): + if filename in [NOTICE_FILE, 'board-2.bin']: + continue + + to_remove.append(filename) + + # investigate what changes are needed + for filepath in fw.get_files_with_path(): + filename = os.path.basename(filepath) + dest = os.path.join(destdir, filename) + + if not os.path.exists(dest): + to_add.append(filename) + continue + + if not filecmp.cmp(filepath, dest): + to_update.append(filename) + + to_remove.remove(filename) + + if len(to_add) > 0 or len(to_update) > 0 or len(to_remove) > 0: + if len(to_update) > 0 or len(to_remove) > 0: + action = 'update' + else: + action = 'add' + + logger.info('Installing %s to %s' % (fw.fw_ver, destdir)) + installed = [] + + for filepath in fw.get_files_with_path(): + destpath = install_file(args, filepath, destdir, + os.path.basename(filepath)) + installed.append(destpath) + + # install notice file (every release must have a notice file) + destpath = install_file(args, fw.get_notice_path(), destdir, + fw.notice_filename) + installed.append(destpath) + + # TODO: whence is not working with ath12k + if action == 'update': + # updating an existing firmware file + whencepath = whence_update(linux_firmware, installed, fw.fw_ver) + else: + # adding a new firmware file + whencepath = whence_add(linux_firmware, installed, fw.fw_ver) + + if whencepath is not None: + installed.append(whencepath) + + git_add(args, linux_firmware, installed) + + for filename in to_remove: + filepath = os.path.join(ath12kdir, hw.get_path(), filename) + + if os.path.basename(filepath) == 'regdb.bin': + logger.debug('ignore %s so that it is not removed from target' % (filepath)) + continue + + logger.info('\trm %s' % (filepath)) + + # even git_rm() removes the file need to remove the + # file separately in case --commit is not used + os.remove(filepath) + + git_rm(args, linux_firmware, [filepath]) + installed.append(filepath) + + # "ath12k: QCA6390 hw2.0: update to WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1" + msg = 'ath12k: %s: %s to %s' % (hw.name, + action, + fw.fw_ver) + + git_commit(args, msg, linux_firmware, installed) + else: + logger.debug('No update needed in %s for %s' % (hw.name, fw.fw_ver)) + + +def main(): + global logger + + logger = logging.getLogger('ath12k-fw-repo') + + parser = argparse.ArgumentParser( + description='Install firmware images from the ath12k-firmware git repository. Run it from the top directory of the working tree.') + + parser.add_argument('--debug', action='store_true', + help='Enable debug messages.') + parser.add_argument('--dry-run', action='store_true', + help='Do not run any actual commands.') + + parser.add_argument('--check', action='store_true', + help='Check the ath12k-firmware repository content for validity.') + parser.add_argument('--list', action='store_true', + help='List all files found from the ath12k-firmware repository.') + + parser.add_argument('--list-hardware', action='store_true', + help='List all possible hardware versions found from the ath12k-firmware repository.') + + parser.add_argument('--list-branches', action='store', + nargs=2, + help='List all firmware branches for for this hardware version.') + + parser.add_argument('--list-releases', action='store', + nargs=3, + help='List all releases from a firmware branch.') + + parser.add_argument('--list-lib-dir', action='store', + nargs=1, metavar='LIB_FIRMWARE_DIRECTORY', + help='List all files found from the specified directory, which can either be a linux-firmware repository or /lib/firmware directory.') + + parser.add_argument('--install', action='store', nargs=1, metavar='DESTINATION', + help='Install all ath12k firmware images to DESTINATION folder, for example /lib/firmware.') + + parser.add_argument('--commit', action='store_true', + help='When installing files also git commit them, for example when updating linux-firmware.git.') + + parser.add_argument('--get-latest-in-branch', action='store', nargs=3, + metavar=('HW', 'HWVER', 'BRANCH'), + help='Show latest firmware version from a firmware branch. Just outputs the version for easy parsing in scripts.') + + parser.add_argument('--get-latest', action='store', nargs=2, + metavar=('HW', 'HWVER'), + help='Show latest firmware version for hardware version. Just outputs the version for easy parsing in scripts.') + + args = parser.parse_args() + + if args.debug: + logging.basicConfig(format='%(levelname)s: %(message)s') + logger.setLevel(logging.DEBUG) + else: + logging.basicConfig(format='%(message)s') + logger.setLevel(logging.INFO) + + # commands + if args.check: + cmd_check(args) + elif args.list: + cmd_list(args) + elif args.list_hardware: + cmd_list_hardware(args) + elif args.list_branches: + cmd_list_branches(args) + elif args.list_releases: + cmd_list_releases(args) + elif args.list_lib_dir: + cmd_list_lib_dir(args) + elif args.install: + cmd_install(args) + elif args.get_latest_in_branch: + cmd_get_latest_in_branch(args) + elif args.get_latest: + cmd_get_latest_in_hw(args) + else: + logger.error('No command defined') + parser.print_usage() + +if __name__ == "__main__": + main() diff --git a/ath12k/board.bin b/ath12k/board.bin new file mode 100644 index 0000000..94a2152 Binary files /dev/null and b/ath12k/board.bin differ diff --git a/ath12k/regdb.bin b/ath12k/regdb.bin new file mode 100644 index 0000000..4eeaded Binary files /dev/null and b/ath12k/regdb.bin differ diff --git a/fedora_server.md b/fedora_server.md index 06c1b0a..0411942 100644 --- a/fedora_server.md +++ b/fedora_server.md @@ -58,7 +58,7 @@ dnf install tpm2-tss # For machines where prioritizing a secure boot environment is important we need to # specify --tpm2-pcrs=0+7 -- 0 meaning the firmware has not changed and 7 meaning # secure boot is enabled -systemd-cryptenroll /dev/nvme0n1p3 --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7 +systemd-cryptenroll /dev/nvme0n1p3 --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs="" # Add tpm2-tss to dracut # Edit /etc/dracut.conf.d/tpm2.conf diff --git a/wireguard/README.md b/wireguard/README.md new file mode 100644 index 0000000..b9d7b73 --- /dev/null +++ b/wireguard/README.md @@ -0,0 +1,62 @@ +# Wireguard Setup + +## Fedora + +```bash +dnf install wireguard +``` + +/etc/sysctl.d/10-wireguard.conf + +```conf +net.ipv4.ip_forward=1 +net.ipv6.conf.all.forwarding=1 +``` + +```bash +sysctl -p +``` + +### Server + +```bash +wg genkey | tee /etc/wireguard/private.key +cat /etc/wireguard/private.key | wg pubkey | tee /etc/wireguard/public.key +``` + +```bash +cat < /etc/wireguard/wg0.conf +[Interface] +Address = 10.10.10.1/24,fd10:10:10::1/64 +ListenPort = 51820 +PrivateKey = $(cat /etc/wireguard/private.key) +SaveConfig = true +PostUp = iptables -t nat -I POSTROUTING -o bridge0 -j MASQUERADE +PostUp = ip6tables -t nat -I POSTROUTING -o bridge0 -j MASQUERADE +PreDown = iptables -t nat -D POSTROUTING -o bridge0 -j MASQUERADE +PreDown = ip6tables -t nat -D POSTROUTING -o bridge0 -j MASQUERADE +EOF +``` + +```bash +wg set wg0 peer ndUMratPyYXKiOlU6AT5lYI7v3iohBAimgZY3/jsWik= allowed-ips 10.10.10.2,fd10:10:10::2 +``` + +### Client + +```conf +[interface] +PrivateKey = KHgXS7zIqqfb46cfUVKvRZesswZcvib71hhYYcN39mQ= +Address = 10.10.10.2/32,fd10:10:10::2/32 + +[Peer] +PublicKey = kzbHUGzYk6Uyan/NFYY5mh3pxf2IX/WzWZtImeyp6Sw= +Endpoint = 2600:1700:1e6c:a81f:793d:7abf:e94d:9bc4:51820 +AllowedIPs = 0.0.0.0/0,::/0 +``` + +### Testing + +```bash +curl -6 icanhazip.com +``` diff --git a/wireguard/add_client.sh b/wireguard/add_client.sh new file mode 100644 index 0000000..2da340d --- /dev/null +++ b/wireguard/add_client.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +export CLIENT_NAME=$1 +export CLIENT_IP_SUFFIX=$2 + +if [ -z $CLIENT_NAME ]; + then echo 'Client name required. `./add_client.sh client_name 3`'; + exit 1; +fi + +if [ -z $CLIENT_IP_SUFFIX ]; + then echo 'Client IP suffix. `./add_client.sh client_name 3`'; + exit 1; +fi + +export SERVER_PUBKEY=$(cat /etc/wireguard/publickey) +mkdir /etc/wireguard/$CLIENT_NAME +cd /etc/wireguard/$CLIENT_NAME +export PRIVKEY=$(wg genkey) +echo $PRIVKEY | tee $CLIENT_NAME"_privkey" +export PUBKEY=$(echo $PRIVKEY | wg pubkey) +echo $PUBKEY | tee $CLIENT_NAME"_pubkey" + +cat > $CLIENT_NAME".conf" <