From f9f947fab6570e8a755e1a6b553385e56556db09 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 29 Jun 2021 22:40:40 -0600 Subject: [PATCH 1/6] Update wk.std.bytes_to_string() --- scripts/wk/std.py | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/scripts/wk/std.py b/scripts/wk/std.py index eb75154b..919c73a4 100644 --- a/scripts/wk/std.py +++ b/scripts/wk/std.py @@ -701,40 +701,25 @@ def bytes_to_string(size, decimals=0, use_binary=True): decimals, use_binary, ) + scale = 1024 if use_binary else 1000 size = float(size) - abs_size = abs(size) - - # Set scale - scale = 1000 - suffix = 'B' - if use_binary: - scale = 1024 - suffix = 'iB' + suffix = ' ' if use_binary else ' ' + units = list('KMGTPEZY') # Convert to sensible units - if abs_size >= scale ** 5: - size /= scale ** 5 - units = 'P' + suffix - elif abs_size >= scale ** 4: - size /= scale ** 4 - units = 'T' + suffix - elif abs_size >= scale ** 3: - size /= scale ** 3 - units = 'G' + suffix - elif abs_size >= scale ** 2: - size /= scale ** 2 - units = 'M' + suffix - elif abs_size >= scale ** 1: - size /= scale ** 1 - units = 'K' + suffix - else: - size /= scale ** 0 - units = f' {" " if use_binary else ""}B' - size = f'{size:0.{decimals}f} {units}' + while units: + if abs(size) < scale: + break + size /= scale + suffix = units.pop(0) + size_str = ( + f'{size:0.{decimals}f} {suffix}' + f'{"iB" if use_binary and suffix.strip() else "B"}' + ) # Done - LOG.debug('string: %s', size) - return size + LOG.debug('string: %s', size_str) + return size_str def choice(choices, prompt='答えろ!'): From 8a685d4e60565d866291aecb02295f9cb87ffc50 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 30 Jun 2021 01:02:03 -0600 Subject: [PATCH 2/6] Add option to include extra images in build-ufd --- scripts/wk/kit/ufd.py | 100 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 9 deletions(-) diff --git a/scripts/wk/kit/ufd.py b/scripts/wk/kit/ufd.py index 3236877e..867a4957 100644 --- a/scripts/wk/kit/ufd.py +++ b/scripts/wk/kit/ufd.py @@ -2,6 +2,7 @@ # vim: sts=2 sw=2 ts=2 import logging +import math import os import shutil @@ -25,6 +26,7 @@ Usage: [--main-kit PATH] [--winpe PATH] [--extra-dir PATH] + [EXTRA_IMAGES...] build-ufd (-h | --help) Options: @@ -42,22 +44,39 @@ Options: -U --update Don't format device, just update ''' LOG = logging.getLogger(__name__) +MIB = 1024 ** 2 ISO_LABEL = f'{KIT_NAME_SHORT}_LINUX' UFD_LABEL = f'{KIT_NAME_SHORT}_UFD' # Functions +def apply_image(part_path, image_path): + """Apply raw image to dev_path using dd.""" + cmd = [ + 'sudo', + 'dd', + 'bs=4M', + f'if={image_path}', + f'of={part_path}', + ] + run_program(cmd) + + def build_ufd(): + # pylint: disable=too-many-statements """Build UFD using selected sources.""" args = docopt(DOCSTRING) if args['--debug']: log.enable_debug_mode() + if args['--update'] and args['EXTRA_IMAGES']: + std.print_warning('Extra images are ignored when updating') log.update_log_path(dest_name='build-ufd', timestamp=True) try_print = std.TryAndPrint() try_print.add_error('FileNotFoundError') try_print.catch_all = False - try_print.verbose = True try_print.indent = 2 + try_print.verbose = True + try_print.width = 64 # Show header std.print_success(KIT_NAME_FULL) @@ -67,7 +86,8 @@ def build_ufd(): # Verify selections ufd_dev = verify_ufd(args['--ufd-device']) sources = verify_sources(args, SOURCES) - show_selections(args, sources, ufd_dev, SOURCES) + extra_images = [io.case_insensitive_path(i) for i in args['EXTRA_IMAGES']] + show_selections(args, sources, ufd_dev, SOURCES, extra_images) if not args['--force']: confirm_selections(update=args['--update']) @@ -84,6 +104,7 @@ def build_ufd(): function=create_table, dev_path=ufd_dev, use_mbr=args['--use-mbr'], + images=args['EXTRA_IMAGES'], ) try_print.run( message='Setting boot flag...', @@ -131,6 +152,18 @@ def build_ufd(): overwrite=True, ) + # Apply extra images + if not args['--update']: + std.print_standard(' ') + std.print_info('Apply Extra Images') + for part_num, image_path in enumerate(extra_images): + try_print.run( + message=f'Applying {image_path.name}...', + function=apply_image, + part_path=f'{str(ufd_dev_first_partition)[:-1]}{part_num+2}', + image_path=image_path, + ) + # Update boot entries std.print_standard(' ') std.print_info('Boot Setup') @@ -225,17 +258,41 @@ def copy_source(source, items, overwrite=False): raise FileNotFoundError('One or more items not found') -def create_table(dev_path, use_mbr=False): +def create_table(dev_path, use_mbr=False, images=None): """Create GPT or DOS partition table.""" cmd = [ 'sudo', 'parted', dev_path, - '--script', - '--', + '--script', '--', 'mklabel', 'msdos' if use_mbr else 'gpt', - 'mkpart', 'primary', 'fat32', '4MiB', - '-1s' if use_mbr else '-4MiB', ] + if images: + images = [os.stat(i_path).st_size for i_path in images] + else: + images = [] + start = MIB + end = -1 + + # Calculate partition sizes + ## Align all partitions using 1MiB boundaries for 4K alignment + ## NOTE: Partitions are aligned to 1 MiB boundaries to match parted's usage + ## NOTE 2: Crashing if dev_size can't be set is fine since it's necessary + dev_size = get_block_device_size(dev_path) + part_sizes = [math.ceil(i/MIB) * MIB for i in images] + main_size = dev_size - start*2 - sum(part_sizes) + main_size = math.floor(main_size/MIB) * MIB + images.insert(0, main_size) + part_sizes.insert(0, main_size) + + # Build cmd + for part, real in zip(part_sizes, images): + end = start + real + cmd.append( + f'mkpart primary {"fat32" if start==MIB else "hfs+"} {start}B {end-1}B', + ) + start += part + + # Run cmd run_program(cmd) @@ -270,6 +327,25 @@ def format_partition(dev_path, label): run_program(cmd) +def get_block_device_size(dev_path): + """Get block device size via lsblk, returns int.""" + cmd = [ + 'lsblk', + '--bytes', + '--nodeps', + '--noheadings', + '--output', + 'size', + dev_path, + ] + + # Run cmd + proc = run_program(cmd) + + # Done + return int(proc.stdout.strip()) + + def get_uuid(path): """Get filesystem UUID via findmnt, returns str.""" cmd = [ @@ -361,7 +437,7 @@ def remove_arch(): shutil.rmtree(io.case_insensitive_path('/mnt/UFD/arch')) -def show_selections(args, sources, ufd_dev, ufd_sources): +def show_selections(args, sources, ufd_dev, ufd_sources, extra_images): """Show selections including non-specified options.""" # Sources @@ -374,9 +450,15 @@ def show_selections(args, sources, ufd_dev, ufd_sources): [f' {label+":":<18}', 'Not Specified'], [None, 'YELLOW'], ) - std.print_standard(' ') + + # Extra images + if extra_images: + print(f' {"Extra Images:":<18} {extra_images[0]}') + for image in extra_images[1:]: + print(f' {" ":<18} {image}') # Destination + std.print_standard(' ') std.print_info('Destination') cmd = [ 'lsblk', '--nodeps', '--noheadings', '--paths', From bf6482a594b5d0e554d4fb90a038d59c67dbaac8 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Jul 2021 21:58:47 -0600 Subject: [PATCH 3/6] Fix possible crash in reset_windows_updates() Auto Repairs could end up in an endless boot loop if SoftwareDistribution.old exists before running --- scripts/wk/repairs/win.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index 566cec99..15406f83 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -19,7 +19,12 @@ from wk.exe import ( popen_program, wait_for_procs, ) -from wk.io import delete_folder, get_path_obj, rename_item +from wk.io import ( + delete_folder, + get_path_obj, + non_clobber_path, + rename_item, + ) from wk.kit.tools import download_tool, get_tool_path, run_tool from wk.log import format_log_path, update_log_path from wk.os.win import ( @@ -1229,12 +1234,11 @@ def reset_windows_policies(): def reset_windows_updates(): """Reset Windows Updates.""" system_root = os.environ.get('SYSTEMROOT', 'C:/Windows') + src_path = f'{system_root}/SoftwareDistribution' + dest_path = non_clobber_path(f'{src_path}.old') try: - rename_item( - f'{system_root}/SoftwareDistribution', - f'{system_root}/SoftwareDistribution.old', - ) - delete_folder(f'{system_root}/SoftwareDistribution.old', force=True) + rename_item(src_path, dest_path) + delete_folder(dest_path, force=True) except FileNotFoundError: # Ignore pass From 07bddaae543283094a4acf336fde303a7da2d4f0 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Jul 2021 22:15:41 -0600 Subject: [PATCH 4/6] Include memtest in macOS builds --- setup/macos/install-deps | 7 +++++++ setup/macos/update-base-image | 1 + 2 files changed, 8 insertions(+) diff --git a/setup/macos/install-deps b/setup/macos/install-deps index a17499d9..f95ae488 100755 --- a/setup/macos/install-deps +++ b/setup/macos/install-deps @@ -27,6 +27,13 @@ echo "Installing Gnuplot..." curl -Lo gnuplot.pkg https://ariadne.ms.northwestern.edu/Download/Gnuplot/gnuplot-5.4.1.pkg sudo installer -pkg gnuplot.pkg -target / +# memtest +echo "Installing memtest..." +curl -Lo memtest https://github.com/Vavius/memtest/raw/8aa02c8c34db8dd00f4470e482dace7eaff265c7/memtest +chmod 755 memtest +sudo chown root:root memtest +sudo mv -nv memtest /usr/sbin/ + # mprime echo "Installing mprime..." if [[ "${OS_VERSION:3:2}" -ge "15" ]]; then diff --git a/setup/macos/update-base-image b/setup/macos/update-base-image index 3d985af0..7f254221 100755 --- a/setup/macos/update-base-image +++ b/setup/macos/update-base-image @@ -95,6 +95,7 @@ sed -Ei '' 's!^(root.*)/bin/sh!\1/bin/zsh!' "${WK_PATH}/etc/passwd" # Misc cp -a ../linux/known_networks "${WK_PATH}/.known_networks" cp -a /usr/bin/rsync "${WK_PATH}/usr/bin"/ +cp -a /usr/sbin/memtest "${WK_PATH}/usr/sbin"/ cp -a /usr/sbin/networksetup "${WK_PATH}/usr/sbin"/ cp -a aliases "${WK_PATH}/.aliases" cp -a bashrc "${WK_PATH}/etc/profile" From dd50852a68c98d10482c4a60463290c052bec2c8 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 23 Jul 2021 22:58:28 -0600 Subject: [PATCH 5/6] Enable numlock in Linux --- scripts/numlock | 10 ++++++++++ setup/linux/packages/gui | 1 + .../system/multi-user.target.wants/numlock.service | 1 + .../airootfs/etc/systemd/system/numlock.service | 10 ++++++++++ .../profile_gui/airootfs/etc/skel/.start_desktop_apps | 5 +++++ 5 files changed, 27 insertions(+) create mode 100755 scripts/numlock create mode 120000 setup/linux/profile_base/airootfs/etc/systemd/system/multi-user.target.wants/numlock.service create mode 100644 setup/linux/profile_base/airootfs/etc/systemd/system/numlock.service diff --git a/scripts/numlock b/scripts/numlock new file mode 100755 index 00000000..a30dfdc6 --- /dev/null +++ b/scripts/numlock @@ -0,0 +1,10 @@ +#!/bin/env bash +# +## Enable numlock if no battery is detected +## Credit: https://wiki.archlinux.org/title/Activating_numlock_on_bootup#With_systemd_service + +if ! compgen -G "/sys/class/power_supply/BAT*" >/dev/null; then + for tty in /dev/tty{1..6}; do + /usr/bin/setleds -D +num < "$tty" + done +fi diff --git a/setup/linux/packages/gui b/setup/linux/packages/gui index b7a625ff..4ef1a114 100644 --- a/setup/linux/packages/gui +++ b/setup/linux/packages/gui @@ -21,6 +21,7 @@ mkvtoolnix-cli mpv noto-fonts noto-fonts-cjk +numlockx openbox-patched otf-font-awesome-4 papirus-icon-theme diff --git a/setup/linux/profile_base/airootfs/etc/systemd/system/multi-user.target.wants/numlock.service b/setup/linux/profile_base/airootfs/etc/systemd/system/multi-user.target.wants/numlock.service new file mode 120000 index 00000000..23379751 --- /dev/null +++ b/setup/linux/profile_base/airootfs/etc/systemd/system/multi-user.target.wants/numlock.service @@ -0,0 +1 @@ +/etc/systemd/system/numlock.service \ No newline at end of file diff --git a/setup/linux/profile_base/airootfs/etc/systemd/system/numlock.service b/setup/linux/profile_base/airootfs/etc/systemd/system/numlock.service new file mode 100644 index 00000000..a076df37 --- /dev/null +++ b/setup/linux/profile_base/airootfs/etc/systemd/system/numlock.service @@ -0,0 +1,10 @@ +[Unit] +Description=numlock + +[Service] +ExecStart=/usr/local/bin/numlock +StandardInput=tty +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/setup/linux/profile_gui/airootfs/etc/skel/.start_desktop_apps b/setup/linux/profile_gui/airootfs/etc/skel/.start_desktop_apps index 49151e56..d9e08b46 100755 --- a/setup/linux/profile_gui/airootfs/etc/skel/.start_desktop_apps +++ b/setup/linux/profile_gui/airootfs/etc/skel/.start_desktop_apps @@ -2,6 +2,11 @@ # ## Start desktop apps based on WM +# Numlock +if ! compgen -G "/sys/class/power_supply/BAT*" >/dev/null; then + numlockx & +fi + # Start common apps #picom --backend xrender --xrender-sync --xrender-sync-fence & picom --daemon || picom --daemon --no-vsync From 628592f958b1e06eea6f9497e602e16f4b98573a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 24 Jul 2021 02:40:45 -0600 Subject: [PATCH 6/6] Fix Mac memtest tool sections --- setup/macos/install-deps | 5 +---- setup/macos/update-base-image | 6 +++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/setup/macos/install-deps b/setup/macos/install-deps index f95ae488..60efb25d 100755 --- a/setup/macos/install-deps +++ b/setup/macos/install-deps @@ -29,10 +29,7 @@ sudo installer -pkg gnuplot.pkg -target / # memtest echo "Installing memtest..." -curl -Lo memtest https://github.com/Vavius/memtest/raw/8aa02c8c34db8dd00f4470e482dace7eaff265c7/memtest -chmod 755 memtest -sudo chown root:root memtest -sudo mv -nv memtest /usr/sbin/ +curl -Lo /usr/local/bin/memtest https://github.com/Vavius/memtest/raw/8aa02c8c34db8dd00f4470e482dace7eaff265c7/memtest # mprime echo "Installing mprime..." diff --git a/setup/macos/update-base-image b/setup/macos/update-base-image index 7f254221..b62f75d6 100755 --- a/setup/macos/update-base-image +++ b/setup/macos/update-base-image @@ -92,10 +92,14 @@ rsync -aS /usr/share/zsh "${WK_PATH}/usr/share"/ rsync -aS /usr/local/share/zsh "${WK_PATH}/usr/local/share"/ sed -Ei '' 's!^(root.*)/bin/sh!\1/bin/zsh!' "${WK_PATH}/etc/passwd" +# memtest +sudo mv -nv "${WK_PATH}/usr/local/bin/memtest" "${WK_PATH}/usr/sbin"/ +sudo chown 0:0 "${WK_PATH}/usr/sbin/memtest" +sudo chmod 755 "${WK_PATH}/usr/sbin/memtest" + # Misc cp -a ../linux/known_networks "${WK_PATH}/.known_networks" cp -a /usr/bin/rsync "${WK_PATH}/usr/bin"/ -cp -a /usr/sbin/memtest "${WK_PATH}/usr/sbin"/ cp -a /usr/sbin/networksetup "${WK_PATH}/usr/sbin"/ cp -a aliases "${WK_PATH}/.aliases" cp -a bashrc "${WK_PATH}/etc/profile"