Compare commits
153 commits
type-hinti
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 875166b683 | |||
| 179748c469 | |||
| ffcee1156a | |||
| edd944a325 | |||
| 75119c15ad | |||
| e6db63c8b0 | |||
| e388b77639 | |||
| bbdef56df2 | |||
| 6a5a944ea0 | |||
| 3621914312 | |||
| 0ef9412995 | |||
| 0335797a5d | |||
| 2a07aebff3 | |||
| 244d917c73 | |||
| 13b8dc8696 | |||
| 58576cbdb4 | |||
| a3a7b25512 | |||
| 50033f42f6 | |||
| d00d625142 | |||
| 97842e82f2 | |||
| 4a54b6e00c | |||
| ee7c7c2448 | |||
| 3aff533c4d | |||
| a256e6e764 | |||
| cc3e36c60d | |||
| f91eac3ec3 | |||
| 667de2d672 | |||
| 272fd3e43f | |||
| 58069f9db2 | |||
| 33d266f83e | |||
| e84feb3160 | |||
| 243fb78837 | |||
| 565ec32294 | |||
| 694eec911b | |||
| 44b7f786e7 | |||
| f7d212d115 | |||
| 3230984a4f | |||
| 9f4b0ffa82 | |||
| 75bad41e93 | |||
| 8602723adb | |||
| b01cb6ed26 | |||
| aaae24b790 | |||
| 94c8c2ba01 | |||
| 80a0d9874a | |||
| e85d9c220e | |||
| 864a546fe3 | |||
| 3ce134901a | |||
| 6d62bfeaea | |||
| c18e82af75 | |||
| 9f5c097f81 | |||
| 42c72f20f4 | |||
| 4e887c318b | |||
| e39a2acf26 | |||
| 8ab56ae9d8 | |||
| 1c6f0f5f28 | |||
| 4aedea65c7 | |||
| d7067af522 | |||
| 484f13dc29 | |||
| 868932c5e4 | |||
| 17a62d6f36 | |||
| b20b612315 | |||
| 73bd58a973 | |||
| 33e9cde0f4 | |||
| ee9d316217 | |||
| f7345a8a54 | |||
| 075a0d8541 | |||
| 5147a4105f | |||
| d933ec6415 | |||
| f5681a93d8 | |||
| dbe4a342cc | |||
| 460fd9c952 | |||
| 7603b93338 | |||
| 42720d322b | |||
| 6bef46bb4d | |||
| 670619b65e | |||
| b9c4c9c32f | |||
| e7642bdc63 | |||
| a12995b37d | |||
| ee34e692dd | |||
| 2134536960 | |||
| 47ccd7dd91 | |||
| 24e4f7ddcc | |||
| bddf47816f | |||
| 0c1c65182c | |||
| cda5aee714 | |||
| 7c16d13f65 | |||
| 840008d8cd | |||
| 090a9f2b96 | |||
| 4467369811 | |||
| a20fdf7bd3 | |||
| df1d2b713f | |||
| 4a34f5477d | |||
| 0ace951380 | |||
| 6a1cf98d0b | |||
| 8f14fd2442 | |||
| a78a077bdf | |||
| d101ec627f | |||
| 408a0c6114 | |||
| ebd1bbda18 | |||
| 7499639c5c | |||
| d6f3455236 | |||
| 55d752dd8b | |||
| f8fc38a78b | |||
| 895d8d2f0a | |||
| 815cfde84a | |||
| 9a7fdba3f9 | |||
| f9a6850c1a | |||
| 172f00e4e9 | |||
| 86203a4b86 | |||
| 8e234ce0cd | |||
| 9689dcfeab | |||
| cafa2c24fb | |||
| 3ff61e9948 | |||
| 9980dab27b | |||
| 55ce4d8ded | |||
| 662f8c1254 | |||
| d34df7ae07 | |||
| dfcc717048 | |||
| 21cbe5d445 | |||
| d94e9097b7 | |||
| 228a5f640e | |||
| acd484f891 | |||
| d958945fe8 | |||
| 3e10f2cb8c | |||
| 9810c630f6 | |||
| c3bf5f6730 | |||
| c63b388f81 | |||
| 20a0881421 | |||
| 203ad715e0 | |||
| 986c870090 | |||
| 4feb15182e | |||
| 88d3ade64d | |||
| 4202d3c1dc | |||
| bcb9228234 | |||
| f2ab06374b | |||
| a2c41fbaf2 | |||
| 7e6cfa1896 | |||
| 13e14e6734 | |||
| 45a7f84e19 | |||
| 86f748c599 | |||
| becc564269 | |||
| 7ab6ccbd36 | |||
| 8e7d202c32 | |||
| 05de5c7294 | |||
| fc2b90a2c0 | |||
| de7993c39c | |||
| dbb606601d | |||
| 1dc22d5991 | |||
| f50ea711e6 | |||
| 2cce572acf | |||
| a253fdc80f | |||
| 386a8b7000 | |||
| f654052f1d |
132 changed files with 6982 additions and 6606 deletions
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2021 Alan Mason
|
||||
Copyright (c) 2023 Alan Mason
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ if defined L_NCMD (
|
|||
rem use Powershell's window instead of %CON%
|
||||
echo UAC.ShellExecute "%POWERSHELL%", "%ps_args% -File "%script%"", "", "runas", 3 >> "%bin%\tmp\Elevate.vbs"
|
||||
) else (
|
||||
echo UAC.ShellExecute "%CON%", "-run %POWERSHELL% %ps_args% -File "%script%" -new_console:n", "", "runas", 1 >> "%bin%\tmp\Elevate.vbs"
|
||||
echo UAC.ShellExecute "%CON%", "-run %POWERSHELL% %ps_args% -File "^"%script%^"" -new_console:n", "", "runas", 1 >> "%bin%\tmp\Elevate.vbs"
|
||||
)
|
||||
|
||||
rem Run
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
"""WizardKit: Auto Repair Tool"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
from typing import Any
|
||||
|
||||
import wk
|
||||
|
||||
|
||||
|
|
@ -8,9 +10,14 @@ import wk
|
|||
REBOOT_STR = wk.ui.ansi.color_string('Reboot', 'YELLOW')
|
||||
class MenuEntry():
|
||||
"""Simple class to allow cleaner code below."""
|
||||
def __init__(self, name, function=None, selected=True, **kwargs):
|
||||
self.name = name
|
||||
self.details = {
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
function: str | None = None,
|
||||
selected: bool = True,
|
||||
**kwargs):
|
||||
self.name: str = name
|
||||
self.details: dict[str, Any] = {
|
||||
'Function': function,
|
||||
'Selected': selected,
|
||||
**kwargs,
|
||||
|
|
@ -54,14 +61,14 @@ BASE_MENUS = {
|
|||
),
|
||||
'Manual Steps': (
|
||||
MenuEntry('AdwCleaner', 'auto_adwcleaner'),
|
||||
MenuEntry('UninstallView', 'auto_uninstallview'),
|
||||
MenuEntry('Bulk Crap Uninstaller', 'auto_bcuninstaller'),
|
||||
MenuEntry('Enable Windows Updates', 'auto_windows_updates_enable'),
|
||||
),
|
||||
},
|
||||
'Options': (
|
||||
MenuEntry('Kill Explorer', selected=False),
|
||||
MenuEntry('Run AVRemover (once)'),
|
||||
MenuEntry('Run RKill'),
|
||||
MenuEntry('Run TDSSKiller (once)'),
|
||||
MenuEntry('Sync Clock'),
|
||||
MenuEntry('Use Autologon', selected=False),
|
||||
),
|
||||
|
|
@ -76,7 +83,6 @@ PRESETS = {
|
|||
'Default': { # Will be expanded at runtime using BASE_MENUS
|
||||
'Options': (
|
||||
'Run RKill',
|
||||
'Run TDSSKiller (once)',
|
||||
'Sync Clock',
|
||||
),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,15 +1,22 @@
|
|||
"""WizardKit: Auto System Setup Tool"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
from typing import Any
|
||||
|
||||
import wk
|
||||
|
||||
|
||||
# Classes
|
||||
class MenuEntry():
|
||||
"""Simple class to allow cleaner code below."""
|
||||
def __init__(self, name, function=None, selected=True, **kwargs):
|
||||
self.name = name
|
||||
self.details = {
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
function: str | None = None,
|
||||
selected: bool = True,
|
||||
**kwargs):
|
||||
self.name: str = name
|
||||
self.details: dict[str, Any] = {
|
||||
'Function': function,
|
||||
'Selected': selected,
|
||||
**kwargs,
|
||||
|
|
@ -26,14 +33,17 @@ BASE_MENUS = {
|
|||
MenuEntry('Set Custom Power Plan', 'auto_set_custom_power_plan'),
|
||||
),
|
||||
'Install Software': (
|
||||
MenuEntry('Visual C++ Runtimes', 'auto_install_vcredists'),
|
||||
MenuEntry('Winget', 'auto_install_winget'),
|
||||
MenuEntry('Firefox', 'auto_install_firefox'),
|
||||
MenuEntry('LibreOffice', 'auto_install_libreoffice', selected=False),
|
||||
MenuEntry('Open Shell', 'auto_install_open_shell'),
|
||||
MenuEntry('Software Bundle', 'auto_install_software_bundle'),
|
||||
MenuEntry('Software Upgrades', 'auto_install_software_upgrades'),
|
||||
MenuEntry('Visual C++ Runtimes', 'auto_install_vcredists'),
|
||||
),
|
||||
'Configure System': (
|
||||
MenuEntry('Open Shell', 'auto_config_open_shell'),
|
||||
MenuEntry('Disable Password Expiration', 'auto_disable_password_expiration'),
|
||||
MenuEntry('Enable BSoD MiniDumps', 'auto_enable_bsod_minidumps'),
|
||||
MenuEntry('Enable RegBack', 'auto_enable_regback'),
|
||||
MenuEntry('Enable System Restore', 'auto_system_restore_enable'),
|
||||
|
|
@ -61,6 +71,7 @@ BASE_MENUS = {
|
|||
'Run Programs': (
|
||||
MenuEntry('Device Manager', 'auto_open_device_manager'),
|
||||
MenuEntry('HWiNFO Sensors', 'auto_open_hwinfo_sensors'),
|
||||
MenuEntry('Microsoft Store Updates', 'auto_open_microsoft_store_updates'),
|
||||
MenuEntry('Snappy Driver Installer', 'auto_open_snappy_driver_installer_origin'),
|
||||
MenuEntry('Windows Activation', 'auto_open_windows_activation'),
|
||||
MenuEntry('Windows Updates', 'auto_open_windows_updates'),
|
||||
|
|
@ -90,6 +101,9 @@ PRESETS = {
|
|||
'Install Software': (
|
||||
'Firefox', # Needed to handle profile upgrade nonsense
|
||||
),
|
||||
'Run Programs': (
|
||||
'Microsoft Store Updates',
|
||||
),
|
||||
'System Summary': (
|
||||
'Operating System',
|
||||
'Windows Activation',
|
||||
|
|
|
|||
13
scripts/check_av.ps1
Normal file
13
scripts/check_av.ps1
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# WizardKit: Check Antivirus
|
||||
|
||||
#Requires -Version 3.0
|
||||
if (Test-Path Env:\DEBUG) {
|
||||
Set-PSDebug -Trace 1
|
||||
}
|
||||
$Host.UI.RawUI.WindowTitle = "WizardKit: Check Antivirus"
|
||||
$Host.UI.RawUI.BackgroundColor = "black"
|
||||
$Host.UI.RawUI.ForegroundColor = "white"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
# Main
|
||||
Get-CimInstance -Namespace "root\SecurityCenter2" -ClassName AntivirusProduct | select displayName,productState | ConvertTo-Json
|
||||
13
scripts/check_partition_alignment.ps1
Normal file
13
scripts/check_partition_alignment.ps1
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# WizardKit: Check Partition Alignment
|
||||
|
||||
#Requires -Version 3.0
|
||||
if (Test-Path Env:\DEBUG) {
|
||||
Set-PSDebug -Trace 1
|
||||
}
|
||||
$Host.UI.RawUI.WindowTitle = "WizardKit: Check Partition Alignment"
|
||||
$Host.UI.RawUI.BackgroundColor = "black"
|
||||
$Host.UI.RawUI.ForegroundColor = "white"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
# Main
|
||||
Get-CimInstance -Query "Select * from Win32_DiskPartition" | select Name,Size,StartingOffset | ConvertTo-Json
|
||||
|
|
@ -2,19 +2,10 @@
|
|||
"""WizardKit: ddrescue TUI"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
from docopt import docopt
|
||||
|
||||
import wk
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
docopt(wk.clone.ddrescue.DOCSTRING)
|
||||
except SystemExit:
|
||||
print('')
|
||||
wk.ui.cli.pause('Press Enter to exit...')
|
||||
raise
|
||||
|
||||
try:
|
||||
wk.clone.ddrescue.main()
|
||||
except SystemExit:
|
||||
|
|
|
|||
13
scripts/disable_password_expiration.ps1
Normal file
13
scripts/disable_password_expiration.ps1
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# WizardKit: Disable Password Expiration (Local Accounts)
|
||||
|
||||
#Requires -Version 3.0
|
||||
if (Test-Path Env:\DEBUG) {
|
||||
Set-PSDebug -Trace 1
|
||||
}
|
||||
$Host.UI.RawUI.WindowTitle = "Disable Password Expiration"
|
||||
$Host.UI.RawUI.BackgroundColor = "black"
|
||||
$Host.UI.RawUI.ForegroundColor = "white"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
# Main
|
||||
Get-LocalUser | Set-LocalUser -PasswordNeverExpires $true
|
||||
|
|
@ -5,9 +5,17 @@ python.exe -i embedded_python_env.py
|
|||
"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
import pickle
|
||||
import wk
|
||||
|
||||
|
||||
# Functions
|
||||
def load_state():
|
||||
with open('debug/state.pickle', 'rb') as f:
|
||||
return pickle.load(f)
|
||||
|
||||
|
||||
# Main
|
||||
wk.ui.cli.print_colored(
|
||||
(wk.cfg.main.KIT_NAME_FULL, ': ', 'Debug Console'),
|
||||
('GREEN', None, 'YELLOW'),
|
||||
|
|
|
|||
|
|
@ -2,19 +2,10 @@
|
|||
"""WizardKit: Hardware Diagnostics"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
from docopt import docopt
|
||||
|
||||
import wk
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
docopt(wk.hw.diags.DOCSTRING)
|
||||
except SystemExit:
|
||||
print('')
|
||||
wk.ui.cli.pause('Press Enter to exit...')
|
||||
raise
|
||||
|
||||
try:
|
||||
wk.hw.diags.main()
|
||||
except SystemExit:
|
||||
|
|
|
|||
37
scripts/install_winget.ps1
Normal file
37
scripts/install_winget.ps1
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# WizardKit: Install winget (if needed)
|
||||
|
||||
#Requires -Version 3.0
|
||||
if (Test-Path Env:\DEBUG) {
|
||||
Set-PSDebug -Trace 1
|
||||
}
|
||||
$Host.UI.RawUI.WindowTitle = "WizardKit: Winget installer"
|
||||
$Host.UI.RawUI.BackgroundColor = "black"
|
||||
$Host.UI.RawUI.ForegroundColor = "white"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
# STATIC VARIABLES
|
||||
$EXIT_OK = 0
|
||||
$EXIT_INSTALLED = 1
|
||||
$EXIT_FAILED_TO_INSTALL = 2
|
||||
|
||||
# Main
|
||||
$NeedsInstalled = $false
|
||||
try {
|
||||
$_ = $(winget --version)
|
||||
}
|
||||
catch {
|
||||
$NeedsInstalled = $true
|
||||
}
|
||||
|
||||
# Install
|
||||
if (! $NeedsInstalled) {
|
||||
exit $EXIT_INSTALLED
|
||||
}
|
||||
try {
|
||||
Add-AppxPackage -ErrorAction Stop -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe
|
||||
}
|
||||
catch {
|
||||
exit $EXIT_FAILED_TO_INSTALL
|
||||
}
|
||||
|
||||
exit $EXIT_OK
|
||||
7
scripts/journal-datarec-monitor
Executable file
7
scripts/journal-datarec-monitor
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
## Monitor journal log for data recovery related events
|
||||
|
||||
echo -e 'Monitoring journal output...\n'
|
||||
journalctl -kf \
|
||||
| grep -Ei --color=always 'ata|nvme|scsi|sd[a..z]+|usb|comreset|critical|error'
|
||||
|
|
@ -74,6 +74,14 @@ if __name__ == '__main__':
|
|||
log_dir = wk.log.format_log_path(tool=True).parent
|
||||
USE_NETWORK = False
|
||||
|
||||
# Windows 11 workaround
|
||||
if wk.os.win.OS_VERSION == 11:
|
||||
appid_services = ['appid', 'appidsvc', 'applockerfltr']
|
||||
for svc in appid_services:
|
||||
wk.os.win.stop_service(svc)
|
||||
if any([wk.os.win.get_service_status(s) != 'stopped' for s in appid_services]):
|
||||
raise wk.std.GenericWarning('Failed to stop AppID services')
|
||||
|
||||
# Try to mount server
|
||||
try:
|
||||
USE_NETWORK = use_network_sdio()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ from . import log
|
|||
from . import main
|
||||
from . import music
|
||||
from . import net
|
||||
from . import python
|
||||
from . import repairs
|
||||
from . import setup
|
||||
from . import sources
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
"""WizardKit: Config - ddrescue"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
# Layout
|
||||
TMUX_SIDE_WIDTH = 21
|
||||
TMUX_LAYOUT = OrderedDict({
|
||||
TMUX_LAYOUT = {
|
||||
'Source': {'height': 2, 'Check': True},
|
||||
'Started': {'width': TMUX_SIDE_WIDTH, 'Check': True},
|
||||
'Progress': {'width': TMUX_SIDE_WIDTH, 'Check': True},
|
||||
})
|
||||
}
|
||||
|
||||
# ddrescue
|
||||
AUTO_PASS_THRESHOLDS = {
|
||||
|
|
@ -39,7 +37,7 @@ DDRESCUE_SETTINGS = {
|
|||
'--retry-passes': {'Selected': True, 'Value': '0', },
|
||||
'--reverse': {'Selected': False, },
|
||||
'--skip-size': {'Selected': True, 'Value': '0.001,0.02', }, # Percentages of source size
|
||||
'--test-mode': {'Selected': False, 'Value': 'test.map', },
|
||||
'--test-mode': {'Selected': False, },
|
||||
'--timeout': {'Selected': True, 'Value': '30m', },
|
||||
'-vvvv': {'Selected': True, 'Hidden': True, },
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,8 +20,13 @@ BADBLOCKS_REGEX = re.compile(
|
|||
)
|
||||
BADBLOCKS_RESULTS_REGEX = re.compile(r'^(.*?)\x08.*\x08(.*)')
|
||||
BADBLOCKS_SKIP_REGEX = re.compile(r'^(Checking|\[)', re.IGNORECASE)
|
||||
CPU_CRITICAL_TEMP = 99
|
||||
CPU_FAILURE_TEMP = 90
|
||||
CPU_TEMPS = {
|
||||
'Cooling Delta': 25,
|
||||
'Cooling Low Cutoff': 50,
|
||||
'Critical': 100,
|
||||
'Idle Delta': 25,
|
||||
'Idle High': 70,
|
||||
}
|
||||
CPU_TEST_MINUTES = 7
|
||||
IO_GRAPH_WIDTH = 40
|
||||
IO_ALT_TEST_SIZE_FACTOR = 0.01
|
||||
|
|
|
|||
|
|
@ -15,11 +15,12 @@ LAUNCHERS = {
|
|||
'L_ITEM': 'auto_repairs.py',
|
||||
'L_ELEV': 'True',
|
||||
},
|
||||
'2) Windows Updates': {
|
||||
'2) Store & Windows Updates': {
|
||||
'L_TYPE': 'Executable',
|
||||
'L_PATH': r'%SystemRoot%\System32',
|
||||
'L_ITEM': 'control.exe',
|
||||
'L_ARGS': 'update',
|
||||
'Extra Code': ['explorer ms-windows-store:updates'],
|
||||
},
|
||||
'3) Snappy Driver Installer Origin': {
|
||||
'L_TYPE': 'PyScript',
|
||||
|
|
@ -68,6 +69,12 @@ LAUNCHERS = {
|
|||
'L_PATH': 'BlueScreenView',
|
||||
'L_ITEM': 'BlueScreenView.exe',
|
||||
},
|
||||
'BCUninstaller': {
|
||||
'L_TYPE': 'Executable',
|
||||
'L_PATH': 'BCUninstaller',
|
||||
'L_ITEM': 'BCUninstaller.exe',
|
||||
'L_ELEV': 'True',
|
||||
},
|
||||
'ConEmu (as ADMIN)': {
|
||||
'L_TYPE': 'Executable',
|
||||
'L_PATH': 'ConEmu',
|
||||
|
|
@ -97,6 +104,18 @@ LAUNCHERS = {
|
|||
'if /i "%PROCESSOR_ARCHITECTURE%" == "AMD64" set "ARCH=64"',
|
||||
],
|
||||
},
|
||||
'Device Cleanup': {
|
||||
'L_TYPE': 'Executable',
|
||||
'L_PATH': 'DeviceCleanup',
|
||||
'L_ITEM': 'DeviceCleanup.exe',
|
||||
'L_ELEV': 'True',
|
||||
},
|
||||
'Display Driver Uninstaller': {
|
||||
'L_TYPE': 'Executable',
|
||||
'L_PATH': 'DDU',
|
||||
'L_ITEM': 'Display Driver Uninstaller.exe',
|
||||
'L_ELEV': 'True',
|
||||
},
|
||||
'ERUNT': {
|
||||
'L_TYPE': 'Executable',
|
||||
'L_PATH': 'erunt',
|
||||
|
|
@ -248,12 +267,6 @@ LAUNCHERS = {
|
|||
'L_PATH': 'PuTTY',
|
||||
'L_ITEM': 'PUTTY.EXE',
|
||||
},
|
||||
'UninstallView': {
|
||||
'L_TYPE': 'Executable',
|
||||
'L_PATH': 'UninstallView',
|
||||
'L_ITEM': 'UninstallView.exe',
|
||||
'L_ELEV': 'True',
|
||||
},
|
||||
'WizTree': {
|
||||
'L_TYPE': 'Executable',
|
||||
'L_PATH': 'WizTree',
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
"""WizardKit: Config - Python"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
from sys import version_info
|
||||
|
||||
DATACLASS_DECORATOR_KWARGS = {}
|
||||
if version_info.major >= 3 and version_info.minor >= 10:
|
||||
DATACLASS_DECORATOR_KWARGS['slots'] = True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("This file is not meant to be called directly.")
|
||||
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
|
@ -29,6 +29,14 @@ REG_CHROME_UBLOCK_ORIGIN = {
|
|||
)
|
||||
},
|
||||
}
|
||||
REG_WINDOWS_BSOD_MINIDUMPS = {
|
||||
'HKLM': {
|
||||
# Enable small memory dumps
|
||||
r'SYSTEM\CurrentControlSet\Control\CrashControl': (
|
||||
('CrashDumpEnabled', 3, 'DWORD'),
|
||||
)
|
||||
}
|
||||
}
|
||||
REG_WINDOWS_EXPLORER = {
|
||||
'HKLM': {
|
||||
# Allow password sign-in for MS accounts
|
||||
|
|
@ -50,6 +58,10 @@ REG_WINDOWS_EXPLORER = {
|
|||
r'Software\Policies\Microsoft\Windows\DataCollection': (
|
||||
('AllowTelemetry', 0, 'DWORD'),
|
||||
),
|
||||
# Disable floating Bing search widget
|
||||
r'Software\Policies\Microsoft\Edge': (
|
||||
('WebWidgetAllowed', 0, 'DWORD'),
|
||||
),
|
||||
# Disable Edge first run screen
|
||||
r'Software\Policies\Microsoft\MicrosoftEdge\Main': (
|
||||
('PreventFirstRunPage', 1, 'DWORD'),
|
||||
|
|
@ -113,6 +125,7 @@ REG_OPEN_SHELL_SETTINGS = {
|
|||
('ShowedStyle2', 1, 'DWORD'),
|
||||
),
|
||||
r'Software\OpenShell\StartMenu\Settings': (
|
||||
('HighlightNew', 0, 'DWORD'),
|
||||
('MenuStyle', 'Win7', 'SZ'),
|
||||
('RecentPrograms', 'Recent', 'SZ'),
|
||||
('SkinW7', 'Fluent-Metro', 'SZ'),
|
||||
|
|
|
|||
|
|
@ -22,49 +22,39 @@ SOURCES = {
|
|||
'RKill': 'https://download.bleepingcomputer.com/grinler/rkill.exe',
|
||||
'RegDelNull': 'https://live.sysinternals.com/RegDelNull.exe',
|
||||
'RegDelNull64': 'https://live.sysinternals.com/RegDelNull64.exe',
|
||||
'Software Bundle': 'https://ninite.com/.net4.8-7zip-chrome-edge-vlc/ninite.exe',
|
||||
'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe',
|
||||
|
||||
# Visual C++ Runtimes: https://docs.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist
|
||||
'VCRedist_2012_x32': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe',
|
||||
'VCRedist_2012_x64': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe',
|
||||
'VCRedist_2013_x32': 'https://aka.ms/highdpimfc2013x86enu',
|
||||
'VCRedist_2013_x64': 'https://aka.ms/highdpimfc2013x64enu',
|
||||
'VCRedist_2022_x32': 'https://aka.ms/vs/17/release/vc_redist.x86.exe',
|
||||
'VCRedist_2022_x64': 'https://aka.ms/vs/17/release/vc_redist.x64.exe',
|
||||
|
||||
# Build Kit
|
||||
'AIDA64': 'https://download.aida64.com/aida64engineer675.zip',
|
||||
'Adobe Reader DC': 'https://ardownload2.adobe.com/pub/adobe/reader/win/AcrobatDC/2200220191/AcroRdrDC2200220191_en_US.exe',
|
||||
'AIDA64': 'https://download.aida64.com/aida64engineer692.zip',
|
||||
'Adobe Reader DC': 'https://ardownload2.adobe.com/pub/adobe/reader/win/AcrobatDC/2300620360/AcroRdrDC2300620360_en_US.exe',
|
||||
'Aria2': 'https://github.com/aria2/aria2/releases/download/release-1.36.0/aria2-1.36.0-win-32bit-build1.zip',
|
||||
'Autoruns32': 'http://live.sysinternals.com/Autoruns.exe',
|
||||
'Autoruns64': 'http://live.sysinternals.com/Autoruns64.exe',
|
||||
'BleachBit': 'https://download.bleachbit.org/BleachBit-4.4.2-portable.zip',
|
||||
'BlueScreenView32': 'http://www.nirsoft.net/utils/bluescreenview.zip',
|
||||
'BlueScreenView64': 'http://www.nirsoft.net/utils/bluescreenview-x64.zip',
|
||||
'BCUninstaller': 'https://github.com/Klocman/Bulk-Crap-Uninstaller/releases/download/v5.7/BCUninstaller_5.7_portable.zip',
|
||||
'DDU': 'https://www.wagnardsoft.com/DDU/download/DDU%20v18.0.6.8.exe',
|
||||
'ERUNT': 'http://www.aumha.org/downloads/erunt.zip',
|
||||
'Everything32': 'https://www.voidtools.com/Everything-1.4.1.1020.x86.zip',
|
||||
'Everything64': 'https://www.voidtools.com/Everything-1.4.1.1020.x64.zip',
|
||||
'FastCopy': 'https://ftp.vector.co.jp/75/32/2323/FastCopy4.2.0_installer.exe',
|
||||
'Everything32': 'https://www.voidtools.com/Everything-1.4.1.1024.x86.zip',
|
||||
'Everything64': 'https://www.voidtools.com/Everything-1.4.1.1024.x64.zip',
|
||||
'FastCopy': 'https://github.com/FastCopyLab/FastCopyDist2/raw/main/FastCopy5.4.2_installer.exe',
|
||||
'Fluent-Metro': 'https://github.com/bonzibudd/Fluent-Metro/releases/download/v1.5.3/Fluent-Metro_1.5.3.zip',
|
||||
'FurMark': 'https://geeks3d.com/dl/get/696',
|
||||
'HWiNFO': 'https://www.sac.sk/download/utildiag/hwi_730.zip',
|
||||
'LibreOffice32': 'https://download.documentfoundation.org/libreoffice/stable/7.3.6/win/x86/LibreOffice_7.3.6_Win_x86.msi',
|
||||
'LibreOffice64': 'https://download.documentfoundation.org/libreoffice/stable/7.3.6/win/x86_64/LibreOffice_7.3.6_Win_x64.msi',
|
||||
'FurMark': 'https://geeks3d.com/dl/get/728',
|
||||
'HWiNFO': 'https://www.sac.sk/download/utildiag/hwi_764.zip',
|
||||
'LibreOffice32': 'https://download.documentfoundation.org/libreoffice/stable/7.6.2/win/x86/LibreOffice_7.6.2_Win_x86.msi',
|
||||
'LibreOffice64': 'https://download.documentfoundation.org/libreoffice/stable/7.6.2/win/x86_64/LibreOffice_7.6.2_Win_x86-64.msi',
|
||||
'Macs Fan Control': 'https://www.crystalidea.com/downloads/macsfancontrol_setup.exe',
|
||||
'Neutron': 'http://keir.net/download/neutron.zip',
|
||||
'Notepad++': 'https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v8.1.9.3/npp.8.1.9.3.portable.minimalist.7z',
|
||||
'OpenShell': 'https://github.com/Open-Shell/Open-Shell-Menu/releases/download/v4.4.170/OpenShellSetup_4_4_170.exe',
|
||||
'Notepad++': 'https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v8.5.8/npp.8.5.8.portable.minimalist.7z',
|
||||
'OpenShell': 'https://github.com/Open-Shell/Open-Shell-Menu/releases/download/v4.4.191/OpenShellSetup_4_4_191.exe',
|
||||
'PuTTY': 'https://the.earth.li/~sgtatham/putty/latest/w32/putty.zip',
|
||||
'SDIO Torrent': 'https://www.glenn.delahoy.com/downloads/sdio/SDIO_Update.torrent',
|
||||
'UninstallView32': 'https://www.nirsoft.net/utils/uninstallview.zip',
|
||||
'UninstallView64': 'https://www.nirsoft.net/utils/uninstallview-x64.zip',
|
||||
'WizTree': 'https://diskanalyzer.com/files/wiztree_4_10_portable.zip',
|
||||
'WizTree': 'https://diskanalyzer.com/files/wiztree_4_15_portable.zip',
|
||||
'XMPlay': 'https://support.xmplay.com/files/20/xmplay385.zip?v=47090',
|
||||
'XMPlay 7z': 'https://support.xmplay.com/files/16/xmp-7z.zip?v=800962',
|
||||
'XMPlay Game': 'https://support.xmplay.com/files/12/xmp-gme.zip?v=515637',
|
||||
'XMPlay RAR': 'https://support.xmplay.com/files/16/xmp-rar.zip?v=409646',
|
||||
'XMPlay Innocuous': 'https://support.xmplay.com/files/10/Innocuous%20(v1.5).zip?v=155959',
|
||||
'XMPlay Innocuous': 'https://support.xmplay.com/files/10/Innocuous%20(v1.7).zip?v=645281',
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
"""WizardKit: Config - UFD"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from wk.cfg.main import KIT_NAME_FULL
|
||||
|
||||
|
||||
# General
|
||||
SOURCES = OrderedDict({
|
||||
SOURCES = {
|
||||
'Linux': {'Arg': '--linux', 'Type': 'ISO'},
|
||||
'WinPE': {'Arg': '--winpe', 'Type': 'ISO'},
|
||||
'Main Kit': {'Arg': '--main-kit', 'Type': 'KIT'},
|
||||
'Extra Dir': {'Arg': '--extra-dir', 'Type': 'DIR'},
|
||||
})
|
||||
}
|
||||
|
||||
# Definitions: Boot entries
|
||||
BOOT_ENTRIES = {
|
||||
|
|
@ -39,8 +37,6 @@ ITEMS = {
|
|||
),
|
||||
'Linux': (
|
||||
('/arch', '/'),
|
||||
('/EFI/boot', '/EFI/'),
|
||||
('/syslinux', '/'),
|
||||
),
|
||||
'Main Kit': (
|
||||
('/', f'/{KIT_NAME_FULL}/'),
|
||||
|
|
@ -58,6 +54,25 @@ ITEMS = {
|
|||
('/sources/boot.wim', '/sources/'),
|
||||
),
|
||||
}
|
||||
ITEMS_FROM_LIVE = {
|
||||
'WizardKit UFD base': (
|
||||
('/usr/share/WizardKit/', '/'),
|
||||
),
|
||||
'rEFInd': (
|
||||
('/usr/share/refind/drivers_x64/', '/EFI/Boot/drivers_x64/'),
|
||||
('/usr/share/refind/icons/', '/EFI/Boot/icons/'),
|
||||
('/usr/share/refind/refind_x64.efi', '/EFI/Boot/'),
|
||||
),
|
||||
'Syslinux': (
|
||||
('/usr/lib/syslinux/bios/', '/syslinux/'),
|
||||
),
|
||||
'Memtest86': (
|
||||
('/usr/share/memtest86-efi/', '/EFI/Memtest86/'),
|
||||
),
|
||||
'Wimboot': (
|
||||
('/usr/share/wimboot/', '/syslinux/'),
|
||||
),
|
||||
}
|
||||
ITEMS_HIDDEN = (
|
||||
# Linux (all versions)
|
||||
'arch',
|
||||
|
|
|
|||
|
|
@ -38,4 +38,6 @@ WINDOWS_BUILDS = {
|
|||
# Windows 11
|
||||
'10.0.22000': '21H2',
|
||||
'10.0.22621': '22H2',
|
||||
'10.0.22631': '23H2',
|
||||
'10.0.26100': '24H2',
|
||||
}
|
||||
|
|
|
|||
32
scripts/wk/cfg/winget/default.json
Normal file
32
scripts/wk/cfg/winget/default.json
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"$schema": "https://aka.ms/winget-packages.schema.2.0.json",
|
||||
"CreationDate": "2023-06-25T01:40:45.003-00:00",
|
||||
"Sources": [
|
||||
{
|
||||
"Packages": [
|
||||
{
|
||||
"PackageIdentifier": "7zip.7zip"
|
||||
},
|
||||
{
|
||||
"PackageIdentifier": "Google.Chrome"
|
||||
},
|
||||
{
|
||||
"PackageIdentifier": "Microsoft.Edge"
|
||||
},
|
||||
{
|
||||
"PackageIdentifier": "Mozilla.Firefox"
|
||||
},
|
||||
{
|
||||
"PackageIdentifier": "VideoLAN.VLC"
|
||||
}
|
||||
],
|
||||
"SourceDetails": {
|
||||
"Argument": "https://cdn.winget.microsoft.com/cache",
|
||||
"Identifier": "Microsoft.Winget.Source_8wekyb3d8bbwe",
|
||||
"Name": "winget",
|
||||
"Type": "Microsoft.PreIndexed.Package"
|
||||
}
|
||||
}
|
||||
],
|
||||
"WinGetVersion": "1.4.11071"
|
||||
}
|
||||
29
scripts/wk/cfg/winget/vcredists.json
Normal file
29
scripts/wk/cfg/winget/vcredists.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"$schema": "https://aka.ms/winget-packages.schema.2.0.json",
|
||||
"CreationDate": "2023-06-25T01:40:45.003-00:00",
|
||||
"Sources": [
|
||||
{
|
||||
"Packages": [
|
||||
{
|
||||
"PackageIdentifier": "Microsoft.VCRedist.2013.x64"
|
||||
},
|
||||
{
|
||||
"PackageIdentifier": "Microsoft.VCRedist.2013.x86"
|
||||
},
|
||||
{
|
||||
"PackageIdentifier": "Microsoft.VCRedist.2015+.x64"
|
||||
},
|
||||
{
|
||||
"PackageIdentifier": "Microsoft.VCRedist.2015+.x86"
|
||||
}
|
||||
],
|
||||
"SourceDetails": {
|
||||
"Argument": "https://cdn.winget.microsoft.com/cache",
|
||||
"Identifier": "Microsoft.Winget.Source_8wekyb3d8bbwe",
|
||||
"Name": "winget",
|
||||
"Type": "Microsoft.PreIndexed.Package"
|
||||
}
|
||||
}
|
||||
],
|
||||
"WinGetVersion": "1.4.11071"
|
||||
}
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
"""WizardKit: ddrescue-tui module init"""
|
||||
|
||||
from . import block_pair
|
||||
from . import ddrescue
|
||||
from . import image
|
||||
from . import menus
|
||||
from . import state
|
||||
|
|
|
|||
575
scripts/wk/clone/block_pair.py
Normal file
575
scripts/wk/clone/block_pair.py
Normal file
|
|
@ -0,0 +1,575 @@
|
|||
"""WizardKit: ddrescue TUI - Block Pairs"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
import logging
|
||||
import math
|
||||
import os
|
||||
import pathlib
|
||||
import plistlib
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from wk import cfg, exe, std
|
||||
from wk.clone import menus
|
||||
from wk.hw import disk as hw_disk
|
||||
from wk.ui import ansi, cli
|
||||
|
||||
|
||||
# STATIC VARIABLES
|
||||
LOG = logging.getLogger(__name__)
|
||||
DDRESCUE_LOG_REGEX = re.compile(
|
||||
r'^\s*(?P<key>\S+):\s+'
|
||||
r'(?P<size>\d+)\s+'
|
||||
r'(?P<unit>[PTGMKB]i?B?)'
|
||||
r'.*\(\s*(?P<percent>\d+\.?\d*)%\)$',
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
# Classes
|
||||
class BlockPair():
|
||||
"""Object for tracking source to dest recovery data."""
|
||||
def __init__(
|
||||
self,
|
||||
source_dev: hw_disk.Disk,
|
||||
destination: pathlib.Path,
|
||||
working_dir: pathlib.Path,
|
||||
):
|
||||
self.sector_size: int = source_dev.phy_sec
|
||||
self.source: pathlib.Path = pathlib.Path(source_dev.path)
|
||||
self.destination: pathlib.Path = destination
|
||||
self.map_data: dict[str, bool | int] = {}
|
||||
self.map_path: pathlib.Path = pathlib.Path()
|
||||
self.size: int = source_dev.size
|
||||
self.status: dict[str, float | int | str] = {
|
||||
'read-skip': 'Pending',
|
||||
'read-full': 'Pending',
|
||||
'trim': 'Pending',
|
||||
'scrape': 'Pending',
|
||||
}
|
||||
self.test_map: pathlib.Path | None = None
|
||||
self.view_map: bool = 'DISPLAY' in os.environ or 'WAYLAND_DISPLAY' in os.environ
|
||||
self.view_proc: subprocess.Popen | None = None
|
||||
|
||||
# Set map path
|
||||
# e.g. '(Clone|Image)_Model_Serial[_p#]_Size[_Label].map'
|
||||
map_name = f'{source_dev.model}_{source_dev.serial}'
|
||||
if source_dev.bus == 'Image':
|
||||
map_name = 'Image'
|
||||
if source_dev.parent:
|
||||
part_num = re.sub(r"^.*?(\d+)$", r"\1", self.source.name)
|
||||
map_name += f'_p{part_num}'
|
||||
size_str = std.bytes_to_string(
|
||||
size=self.size,
|
||||
use_binary=False,
|
||||
)
|
||||
map_name += f'_{size_str.replace(" ", "")}'
|
||||
if source_dev.raw_details.get('label', ''):
|
||||
map_name += f'_{source_dev.raw_details["label"]}'
|
||||
map_name = map_name.replace(' ', '_')
|
||||
map_name = map_name.replace('/', '_')
|
||||
map_name = map_name.replace('\\', '_')
|
||||
if destination.is_dir():
|
||||
# Imaging
|
||||
self.map_path = pathlib.Path(f'{destination}/Image_{map_name}.map')
|
||||
self.destination = self.map_path.with_suffix('.dd')
|
||||
self.destination.touch()
|
||||
else:
|
||||
# Cloning
|
||||
self.map_path = pathlib.Path(f'{working_dir}/Clone_{map_name}.map')
|
||||
|
||||
# Create map file if needed
|
||||
# NOTE: We need to set the domain size for --complete-only to work
|
||||
if not self.map_path.exists():
|
||||
self.map_path.write_text(
|
||||
data=cfg.ddrescue.DDRESCUE_MAP_TEMPLATE.format(
|
||||
name=cfg.main.KIT_NAME_FULL,
|
||||
size=self.size,
|
||||
),
|
||||
encoding='utf-8',
|
||||
)
|
||||
|
||||
# Set initial status
|
||||
self.set_initial_status()
|
||||
|
||||
def __getstate__(self):
|
||||
"""Override to allow pickling ddrescue.State() objects."""
|
||||
bp_state = self.__dict__.copy()
|
||||
del bp_state['view_proc']
|
||||
return bp_state
|
||||
|
||||
def get_error_size(self) -> int:
|
||||
"""Get error size in bytes, returns int."""
|
||||
return self.size - self.get_rescued_size()
|
||||
|
||||
def get_percent_recovered(self) -> float:
|
||||
"""Get percent rescued from map_data, returns float."""
|
||||
return 100 * self.map_data.get('rescued', 0) / self.size
|
||||
|
||||
def get_rescued_size(self) -> int:
|
||||
"""Get rescued size using map data.
|
||||
|
||||
NOTE: Returns 0 if no map data is available.
|
||||
"""
|
||||
self.load_map_data()
|
||||
return self.map_data.get('rescued', 0)
|
||||
|
||||
def load_map_data(self) -> None:
|
||||
"""Load map data from file.
|
||||
|
||||
NOTE: If the file is missing it is assumed that recovery hasn't
|
||||
started yet so default values will be returned instead.
|
||||
"""
|
||||
data: dict[str, bool | int] = {'full recovery': False, 'pass completed': False}
|
||||
|
||||
# Get output from ddrescuelog
|
||||
cmd = [
|
||||
'ddrescuelog',
|
||||
'--binary-prefixes',
|
||||
'--show-status',
|
||||
f'--size={self.size}',
|
||||
self.map_path,
|
||||
]
|
||||
proc = exe.run_program(cmd, check=False)
|
||||
|
||||
# Parse output
|
||||
for line in proc.stdout.splitlines():
|
||||
_r = DDRESCUE_LOG_REGEX.search(line)
|
||||
if _r:
|
||||
if _r.group('key') == 'rescued' and _r.group('percent') == '100':
|
||||
# Fix rounding errors from ddrescuelog output
|
||||
data['rescued'] = self.size
|
||||
else:
|
||||
data[_r.group('key')] = std.string_to_bytes(
|
||||
f'{_r.group("size")} {_r.group("unit")}',
|
||||
)
|
||||
data['pass completed'] = 'current status: finished' in line.lower()
|
||||
|
||||
# Check if 100% done (only if map is present and non-zero size
|
||||
# NOTE: ddrescuelog returns 0 (i.e. 100% done) for empty files
|
||||
if self.map_path.exists() and self.map_path.stat().st_size != 0:
|
||||
cmd = [
|
||||
'ddrescuelog',
|
||||
'--done-status',
|
||||
f'--size={self.size}',
|
||||
self.map_path,
|
||||
]
|
||||
proc = exe.run_program(cmd, check=False)
|
||||
data['full recovery'] = proc.returncode == 0
|
||||
|
||||
# Done
|
||||
self.map_data.update(data)
|
||||
|
||||
def pass_complete(self, pass_name) -> bool:
|
||||
"""Check if pass_name is complete based on map data, returns bool."""
|
||||
pending_size = self.map_data['non-tried']
|
||||
|
||||
# Full recovery
|
||||
if self.map_data.get('full recovery', False):
|
||||
return True
|
||||
|
||||
# New recovery
|
||||
if 'non-tried' not in self.map_data:
|
||||
return False
|
||||
|
||||
# Initial read skip pass
|
||||
if pass_name == 'read-skip':
|
||||
pass_threshold = cfg.ddrescue.AUTO_PASS_THRESHOLDS[pass_name]
|
||||
if self.get_percent_recovered() >= pass_threshold:
|
||||
return True
|
||||
|
||||
# Recovery in progress
|
||||
if pass_name in ('trim', 'scrape'):
|
||||
pending_size += self.map_data['non-trimmed']
|
||||
if pass_name == 'scrape':
|
||||
pending_size += self.map_data['non-scraped']
|
||||
if pending_size == 0:
|
||||
# This is true when the previous and current passes are complete
|
||||
return True
|
||||
|
||||
# This should never be reached
|
||||
return False
|
||||
|
||||
def safety_check(self) -> None:
|
||||
"""Run safety check and abort if necessary."""
|
||||
# TODO: Expand section to support non-Linux systems
|
||||
dest_size = -1
|
||||
if self.destination.is_block_device():
|
||||
cmd = [
|
||||
'lsblk', '--bytes', '--json',
|
||||
'--nodeps', '--noheadings', '--output=size',
|
||||
self.destination,
|
||||
]
|
||||
json_data = exe.get_json_from_command(cmd)
|
||||
dest_size = json_data['blockdevices'][0]['size']
|
||||
del json_data
|
||||
|
||||
# Check destination size if cloning
|
||||
if not self.destination.is_file() and dest_size < self.size:
|
||||
cli.print_error(f'Invalid destination: {self.destination}')
|
||||
raise std.GenericAbort()
|
||||
|
||||
def set_initial_status(self) -> None:
|
||||
"""Read map data and set initial statuses."""
|
||||
self.load_map_data()
|
||||
percent = self.get_percent_recovered()
|
||||
for name in self.status:
|
||||
if self.pass_complete(name):
|
||||
self.status[name] = percent
|
||||
else:
|
||||
# Stop checking
|
||||
if percent > 0:
|
||||
self.status[name] = percent
|
||||
break
|
||||
|
||||
def skip_pass(self, pass_name) -> None:
|
||||
"""Mark pass as skipped if applicable."""
|
||||
if self.status[pass_name] == 'Pending':
|
||||
self.status[pass_name] = 'Skipped'
|
||||
|
||||
def update_progress(self, pass_name) -> None:
|
||||
"""Update progress via map data."""
|
||||
self.load_map_data()
|
||||
|
||||
# Update status
|
||||
percent = self.get_percent_recovered()
|
||||
if percent > 0:
|
||||
self.status[pass_name] = percent
|
||||
|
||||
# Mark future passes as skipped if applicable
|
||||
if percent == 100:
|
||||
status_keys = list(self.status.keys())
|
||||
for pass_n in status_keys[status_keys.index(pass_name)+1:]:
|
||||
self.status[pass_n] = 'Skipped'
|
||||
|
||||
|
||||
# Functions
|
||||
def add_clone_block_pairs(state) -> list[hw_disk.Disk]:
|
||||
"""Add device to device block pairs and set settings if necessary."""
|
||||
source_sep = get_partition_separator(state.source.path.name)
|
||||
dest_sep = get_partition_separator(state.destination.path.name)
|
||||
settings = {}
|
||||
|
||||
# Clone settings
|
||||
settings = state.load_settings(discard_unused_settings=True)
|
||||
|
||||
# Add pairs from previous run
|
||||
if settings['Partition Mapping']:
|
||||
source_parts = []
|
||||
for part_map in settings['Partition Mapping']:
|
||||
bp_source = hw_disk.Disk(
|
||||
f'{state.source.path}{source_sep}{part_map[0]}',
|
||||
)
|
||||
bp_dest = pathlib.Path(
|
||||
f'{state.destination.path}{dest_sep}{part_map[1]}',
|
||||
)
|
||||
source_parts.append(bp_source)
|
||||
state.add_block_pair(bp_source, bp_dest)
|
||||
return source_parts
|
||||
|
||||
# Add pairs from selection
|
||||
source_parts = menus.select_disk_parts('Clone', state.source)
|
||||
if state.source.path.samefile(source_parts[0].path):
|
||||
# Whole disk (or single partition via args), skip settings
|
||||
bp_dest = state.destination.path
|
||||
state.add_block_pair(state.source, bp_dest)
|
||||
return source_parts
|
||||
|
||||
# New run, use new settings file
|
||||
settings['Needs Format'] = True
|
||||
offset = 0
|
||||
user_choice = cli.choice(
|
||||
'Format clone using GPT, MBR, or match Source type?',
|
||||
['G', 'M', 'S'],
|
||||
)
|
||||
if user_choice == 'G':
|
||||
settings['Table Type'] = 'GPT'
|
||||
elif user_choice == 'M':
|
||||
settings['Table Type'] = 'MBR'
|
||||
else:
|
||||
# Match source type
|
||||
settings['Table Type'] = get_table_type(state.source.path)
|
||||
if cli.ask('Create an empty Windows boot partition on the clone?'):
|
||||
settings['Create Boot Partition'] = True
|
||||
offset = 2 if settings['Table Type'] == 'GPT' else 1
|
||||
|
||||
# Add pairs
|
||||
for dest_num, part in enumerate(source_parts):
|
||||
dest_num += offset + 1
|
||||
bp_dest = pathlib.Path(
|
||||
f'{state.destination.path}{dest_sep}{dest_num}',
|
||||
)
|
||||
state.add_block_pair(part, bp_dest)
|
||||
|
||||
# Add to settings file
|
||||
source_num = re.sub(r'^.*?(\d+)$', r'\1', part.path.name)
|
||||
settings['Partition Mapping'].append([source_num, dest_num])
|
||||
|
||||
# Save settings
|
||||
state.save_settings(settings)
|
||||
|
||||
# Done
|
||||
return source_parts
|
||||
|
||||
|
||||
def add_image_block_pairs(state) -> list[hw_disk.Disk]:
|
||||
"""Add device to image file block pairs."""
|
||||
source_parts = menus.select_disk_parts(state.mode, state.source)
|
||||
for part in source_parts:
|
||||
state.add_block_pair(part, state.destination)
|
||||
|
||||
# Done
|
||||
return source_parts
|
||||
|
||||
|
||||
def build_block_pair_report(block_pairs, settings) -> list:
|
||||
"""Build block pair report, returns list."""
|
||||
report = []
|
||||
notes = []
|
||||
if block_pairs:
|
||||
report.append(ansi.color_string('Block Pairs', 'GREEN'))
|
||||
else:
|
||||
# Bail early
|
||||
return report
|
||||
|
||||
# Show block pair mapping
|
||||
if settings and settings['Create Boot Partition']:
|
||||
if settings['Table Type'] == 'GPT':
|
||||
report.append(f'{" —— ":<9} --> EFI System Partition')
|
||||
report.append(f'{" —— ":<9} --> Microsoft Reserved Partition')
|
||||
elif settings['Table Type'] == 'MBR':
|
||||
report.append(f'{" —— ":<9} --> System Reserved')
|
||||
for pair in block_pairs:
|
||||
report.append(f'{pair.source.name:<9} --> {pair.destination.name}')
|
||||
|
||||
# Show resume messages as necessary
|
||||
if settings:
|
||||
if not settings['First Run']:
|
||||
notes.append(
|
||||
ansi.color_string(
|
||||
['NOTE:', 'Clone settings loaded from previous run.'],
|
||||
['BLUE', None],
|
||||
),
|
||||
)
|
||||
if settings['Needs Format'] and settings['Table Type']:
|
||||
msg = f'Destination will be formatted using {settings["Table Type"]}'
|
||||
notes.append(
|
||||
ansi.color_string(
|
||||
['NOTE:', msg],
|
||||
['BLUE', None],
|
||||
),
|
||||
)
|
||||
if any(pair.get_rescued_size() > 0 for pair in block_pairs):
|
||||
notes.append(
|
||||
ansi.color_string(
|
||||
['NOTE:', 'Resume data loaded from map file(s).'],
|
||||
['BLUE', None],
|
||||
),
|
||||
)
|
||||
|
||||
# Add notes to report
|
||||
if notes:
|
||||
report.append(' ')
|
||||
report.extend(notes)
|
||||
|
||||
# Done
|
||||
return report
|
||||
|
||||
|
||||
def build_sfdisk_partition_line(table_type, dev_path, size, details) -> str:
|
||||
"""Build sfdisk partition line using passed details, returns str."""
|
||||
line = f'{dev_path} : size={size}'
|
||||
dest_type = ''
|
||||
source_filesystem = str(details.get('fstype', '')).upper()
|
||||
source_table_type = ''
|
||||
source_type = details.get('parttype', '')
|
||||
|
||||
# Set dest type
|
||||
if re.match(r'^0x\w+$', source_type):
|
||||
# Source is a MBR type
|
||||
source_table_type = 'MBR'
|
||||
if table_type == 'MBR':
|
||||
dest_type = source_type.replace('0x', '').lower()
|
||||
elif re.match(r'^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$', source_type):
|
||||
# Source is a GPT type
|
||||
source_table_type = 'GPT'
|
||||
if table_type == 'GPT':
|
||||
dest_type = source_type.upper()
|
||||
if not dest_type:
|
||||
# Assuming changing table types, set based on FS
|
||||
if source_filesystem in cfg.ddrescue.PARTITION_TYPES.get(table_type, {}):
|
||||
dest_type = cfg.ddrescue.PARTITION_TYPES[table_type][source_filesystem]
|
||||
line += f', type={dest_type}'
|
||||
|
||||
# Safety Check
|
||||
if not dest_type:
|
||||
cli.print_error(f'Failed to determine partition type for: {dev_path}')
|
||||
raise std.GenericAbort()
|
||||
|
||||
# Add extra details
|
||||
if details.get('partlabel', ''):
|
||||
line += f', name="{details["partlabel"]}"'
|
||||
if details.get('partuuid', '') and source_table_type == table_type:
|
||||
# Only add UUID if source/dest table types match
|
||||
line += f', uuid={details["partuuid"].upper()}'
|
||||
|
||||
# Done
|
||||
return line
|
||||
|
||||
|
||||
def get_partition_separator(name) -> str:
|
||||
"""Get partition separator based on device name, returns str."""
|
||||
separator = ''
|
||||
if re.search(r'(loop|mmc|nvme)', name, re.IGNORECASE):
|
||||
separator = 'p'
|
||||
|
||||
return separator
|
||||
|
||||
|
||||
def get_table_type(disk_path) -> str:
|
||||
"""Get disk partition table type, returns str.
|
||||
|
||||
NOTE: If resulting table type is not GPT or MBR
|
||||
then an exception is raised.
|
||||
"""
|
||||
disk_path = str(disk_path)
|
||||
table_type = None
|
||||
|
||||
# Linux
|
||||
if std.PLATFORM == 'Linux':
|
||||
cmd = f'lsblk --json --output=pttype --nodeps {disk_path}'.split()
|
||||
json_data = exe.get_json_from_command(cmd)
|
||||
table_type = json_data['blockdevices'][0].get('pttype', '').upper()
|
||||
table_type = table_type.replace('DOS', 'MBR')
|
||||
|
||||
# macOS
|
||||
if std.PLATFORM == 'Darwin':
|
||||
cmd = ['diskutil', 'list', '-plist', disk_path]
|
||||
proc = exe.run_program(cmd, check=False, encoding=None, errors=None)
|
||||
try:
|
||||
plist_data = plistlib.loads(proc.stdout)
|
||||
except (TypeError, ValueError):
|
||||
# Invalid / corrupt plist data? return empty dict to avoid crash
|
||||
pass
|
||||
else:
|
||||
disk_details = plist_data.get('AllDisksAndPartitions', [{}])[0]
|
||||
table_type = disk_details['Content']
|
||||
table_type = table_type.replace('FDisk_partition_scheme', 'MBR')
|
||||
table_type = table_type.replace('GUID_partition_scheme', 'GPT')
|
||||
|
||||
# Check type
|
||||
if table_type not in ('GPT', 'MBR'):
|
||||
cli.print_error(f'Unsupported partition table type: {table_type}')
|
||||
raise std.GenericAbort()
|
||||
|
||||
# Done
|
||||
return table_type
|
||||
|
||||
|
||||
def prep_destination(
|
||||
state,
|
||||
source_parts: list[hw_disk.Disk],
|
||||
dry_run: bool = True,
|
||||
) -> None:
|
||||
"""Prep destination as necessary."""
|
||||
# TODO: Split into Linux and macOS
|
||||
# logical sector size is not easily found under macOS
|
||||
# It might be easier to rewrite this section using macOS tools
|
||||
dest_prefix = str(state.destination.path)
|
||||
dest_prefix += get_partition_separator(state.destination.path.name)
|
||||
esp_type = 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B'
|
||||
msr_type = 'E3C9E316-0B5C-4DB8-817D-F92DF00215AE'
|
||||
part_num = 0
|
||||
sfdisk_script = []
|
||||
settings = state.load_settings()
|
||||
|
||||
# Bail early
|
||||
if not settings['Needs Format']:
|
||||
return
|
||||
|
||||
# Add partition table settings
|
||||
if settings['Table Type'] == 'GPT':
|
||||
sfdisk_script.append('label: gpt')
|
||||
else:
|
||||
sfdisk_script.append('label: dos')
|
||||
sfdisk_script.append('unit: sectors')
|
||||
sfdisk_script.append('')
|
||||
|
||||
# Add boot partition if requested
|
||||
if settings['Create Boot Partition']:
|
||||
if settings['Table Type'] == 'GPT':
|
||||
part_num += 1
|
||||
sfdisk_script.append(
|
||||
build_sfdisk_partition_line(
|
||||
table_type='GPT',
|
||||
dev_path=f'{dest_prefix}{part_num}',
|
||||
size='260MiB',
|
||||
details={'parttype': esp_type, 'partlabel': 'EFI System'},
|
||||
),
|
||||
)
|
||||
part_num += 1
|
||||
sfdisk_script.append(
|
||||
build_sfdisk_partition_line(
|
||||
table_type=settings['Table Type'],
|
||||
dev_path=f'{dest_prefix}{part_num}',
|
||||
size='16MiB',
|
||||
details={'parttype': msr_type, 'partlabel': 'Microsoft Reserved'},
|
||||
),
|
||||
)
|
||||
elif settings['Table Type'] == 'MBR':
|
||||
part_num += 1
|
||||
sfdisk_script.append(
|
||||
build_sfdisk_partition_line(
|
||||
table_type='MBR',
|
||||
dev_path=f'{dest_prefix}{part_num}',
|
||||
size='100MiB',
|
||||
details={'parttype': '0x7', 'partlabel': 'System Reserved'},
|
||||
),
|
||||
)
|
||||
|
||||
# Add selected partition(s)
|
||||
for part in source_parts:
|
||||
num_sectors = part.size / state.destination.log_sec
|
||||
num_sectors = math.ceil(num_sectors)
|
||||
part_num += 1
|
||||
sfdisk_script.append(
|
||||
build_sfdisk_partition_line(
|
||||
table_type=settings['Table Type'],
|
||||
dev_path=f'{dest_prefix}{part_num}',
|
||||
size=num_sectors,
|
||||
details=part.raw_details,
|
||||
),
|
||||
)
|
||||
|
||||
# Save sfdisk script
|
||||
script_path = (
|
||||
f'{state.working_dir}/'
|
||||
f'sfdisk_{state.destination.path.name}.script'
|
||||
)
|
||||
with open(script_path, 'w', encoding='utf-8') as _f:
|
||||
_f.write('\n'.join(sfdisk_script))
|
||||
|
||||
# Skip real format for dry runs
|
||||
if dry_run:
|
||||
LOG.info('Dry run, refusing to format destination')
|
||||
return
|
||||
|
||||
# Format disk
|
||||
LOG.warning('Formatting destination: %s', state.destination.path)
|
||||
with open(script_path, 'r', encoding='utf-8') as _f:
|
||||
proc = exe.run_program(
|
||||
cmd=['sudo', 'sfdisk', state.destination.path],
|
||||
stdin=_f,
|
||||
check=False,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
cli.print_error('Error(s) encoundtered while formatting destination')
|
||||
raise std.GenericAbort()
|
||||
|
||||
# Update settings
|
||||
settings['Needs Format'] = False
|
||||
state.save_settings(settings)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("This file is not meant to be called directly.")
|
||||
File diff suppressed because it is too large
Load diff
109
scripts/wk/clone/image.py
Normal file
109
scripts/wk/clone/image.py
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
"""WizardKit: ddrescue TUI - State"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
import atexit
|
||||
import logging
|
||||
import pathlib
|
||||
import plistlib
|
||||
import re
|
||||
|
||||
from wk import exe
|
||||
from wk.std import PLATFORM
|
||||
from wk.ui import cli
|
||||
|
||||
|
||||
# STATIC VARIABLES
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Functions
|
||||
def mount_raw_image(path) -> pathlib.Path:
|
||||
"""Mount raw image using OS specific methods, returns pathlib.Path."""
|
||||
loopback_path = None
|
||||
|
||||
if PLATFORM == 'Darwin':
|
||||
loopback_path = mount_raw_image_macos(path)
|
||||
elif PLATFORM == 'Linux':
|
||||
loopback_path = mount_raw_image_linux(path)
|
||||
|
||||
# Check
|
||||
if not loopback_path:
|
||||
cli.print_error(f'Failed to mount image: {path}')
|
||||
|
||||
# Register unmount atexit
|
||||
atexit.register(unmount_loopback_device, loopback_path)
|
||||
|
||||
# Done
|
||||
return loopback_path
|
||||
|
||||
|
||||
def mount_raw_image_linux(path) -> pathlib.Path:
|
||||
"""Mount raw image using losetup, returns pathlib.Path."""
|
||||
loopback_path = None
|
||||
|
||||
# Mount using losetup
|
||||
cmd = [
|
||||
'sudo',
|
||||
'losetup',
|
||||
'--find',
|
||||
'--partscan',
|
||||
'--show',
|
||||
path,
|
||||
]
|
||||
proc = exe.run_program(cmd, check=False)
|
||||
|
||||
# Check result
|
||||
if proc.returncode == 0:
|
||||
loopback_path = proc.stdout.strip()
|
||||
|
||||
# Done
|
||||
return loopback_path
|
||||
|
||||
|
||||
def mount_raw_image_macos(path) -> pathlib.Path:
|
||||
"""Mount raw image using hdiutil, returns pathlib.Path."""
|
||||
loopback_path = None
|
||||
plist_data = {}
|
||||
|
||||
# Mount using hdiutil
|
||||
# plistdata['system-entities'][{}...]
|
||||
cmd = [
|
||||
'hdiutil', 'attach',
|
||||
'-imagekey', 'diskimage-class=CRawDiskImage',
|
||||
'-nomount',
|
||||
'-plist',
|
||||
'-readonly',
|
||||
path,
|
||||
]
|
||||
proc = exe.run_program(cmd, check=False, encoding=None, errors=None)
|
||||
|
||||
# Check result
|
||||
try:
|
||||
plist_data = plistlib.loads(proc.stdout)
|
||||
except plistlib.InvalidFileException:
|
||||
return None
|
||||
for dev in plist_data.get('system-entities', []):
|
||||
dev_path = dev.get('dev-entry', '')
|
||||
if re.match(r'^/dev/disk\d+$', dev_path):
|
||||
loopback_path = dev_path
|
||||
|
||||
# Done
|
||||
return loopback_path
|
||||
|
||||
|
||||
def unmount_loopback_device(path) -> None:
|
||||
"""Unmount loopback device using OS specific methods."""
|
||||
cmd = []
|
||||
|
||||
# Build OS specific cmd
|
||||
if PLATFORM == 'Darwin':
|
||||
cmd = ['hdiutil', 'detach', path]
|
||||
elif PLATFORM == 'Linux':
|
||||
cmd = ['sudo', 'losetup', '--detach', path]
|
||||
|
||||
# Unmount loopback device
|
||||
exe.run_program(cmd, check=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("This file is not meant to be called directly.")
|
||||
273
scripts/wk/clone/menus.py
Normal file
273
scripts/wk/clone/menus.py
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
"""WizardKit: ddrescue TUI - Menus"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
import logging
|
||||
import pathlib
|
||||
|
||||
from wk.cfg.ddrescue import DDRESCUE_SETTINGS
|
||||
from wk.hw.disk import Disk, get_disks
|
||||
from wk.std import GenericAbort, PLATFORM, bytes_to_string
|
||||
from wk.ui import ansi, cli
|
||||
|
||||
|
||||
# STATIC VARIABLES
|
||||
LOG = logging.getLogger(__name__)
|
||||
CLONE_SETTINGS = {
|
||||
'Source': None,
|
||||
'Destination': None,
|
||||
'Create Boot Partition': False,
|
||||
'First Run': True,
|
||||
'Needs Format': False,
|
||||
'Table Type': None,
|
||||
'Partition Mapping': [
|
||||
# (5, 1) ## Clone source partition #5 to destination partition #1
|
||||
],
|
||||
}
|
||||
if PLATFORM == 'Darwin':
|
||||
# TODO: Direct I/O needs more testing under macOS
|
||||
DDRESCUE_SETTINGS['Default']['--idirect'] = {'Selected': False, 'Hidden': True}
|
||||
DDRESCUE_SETTINGS['Default']['--odirect'] = {'Selected': False, 'Hidden': True}
|
||||
MENU_ACTIONS = (
|
||||
'Start',
|
||||
f'Change settings {ansi.color_string("(experts only)", "YELLOW")}',
|
||||
f'Detect drives {ansi.color_string("(experts only)", "YELLOW")}',
|
||||
'Quit')
|
||||
MENU_TOGGLES = {
|
||||
'Auto continue (if recovery % over threshold)': True,
|
||||
'Retry (mark non-rescued sectors "non-tried")': False,
|
||||
}
|
||||
SETTING_PRESETS = (
|
||||
'Default',
|
||||
'Fast',
|
||||
'Safe',
|
||||
)
|
||||
|
||||
|
||||
# Functions
|
||||
def main() -> cli.Menu:
|
||||
"""Main menu, returns wk.ui.cli.Menu."""
|
||||
menu = cli.Menu(title=ansi.color_string('ddrescue TUI: Main Menu', 'GREEN'))
|
||||
menu.separator = ' '
|
||||
|
||||
# Add actions, options, etc
|
||||
for action in MENU_ACTIONS:
|
||||
if not (PLATFORM == 'Darwin' and 'Detect drives' in action):
|
||||
menu.add_action(action)
|
||||
for toggle, selected in MENU_TOGGLES.items():
|
||||
menu.add_toggle(toggle, {'Selected': selected})
|
||||
|
||||
# Done
|
||||
return menu
|
||||
|
||||
|
||||
def settings(mode: str, silent: bool = True) -> cli.Menu:
|
||||
"""Settings menu, returns wk.ui.cli.Menu."""
|
||||
title_text = [
|
||||
ansi.color_string('ddrescue TUI: Expert Settings', 'GREEN'),
|
||||
' ',
|
||||
ansi.color_string(
|
||||
['These settings can cause', 'MAJOR DAMAGE', 'to drives'],
|
||||
['YELLOW', 'RED', 'YELLOW'],
|
||||
),
|
||||
'Please read the manual before making changes',
|
||||
]
|
||||
menu = cli.Menu(title='\n'.join(title_text))
|
||||
menu.separator = ' '
|
||||
preset = 'Default'
|
||||
if not silent:
|
||||
# Ask which preset to use
|
||||
cli.print_standard(
|
||||
f'Available ddrescue presets: {" / ".join(SETTING_PRESETS)}'
|
||||
)
|
||||
preset = cli.choice('Please select a preset:', SETTING_PRESETS)
|
||||
|
||||
# Fix selection
|
||||
for _p in SETTING_PRESETS:
|
||||
if _p.startswith(preset):
|
||||
preset = _p
|
||||
|
||||
# Add default settings
|
||||
menu.add_action('Load Preset')
|
||||
menu.add_action('Main Menu')
|
||||
for name, details in DDRESCUE_SETTINGS['Default'].items():
|
||||
menu.add_option(name, details.copy())
|
||||
|
||||
# Update settings using preset
|
||||
if preset != 'Default':
|
||||
for name, details in DDRESCUE_SETTINGS[preset].items():
|
||||
menu.options[name].update(details.copy())
|
||||
|
||||
# Disable direct output when saving to an image
|
||||
if mode == 'Image':
|
||||
menu.options['--odirect']['Disabled'] = True
|
||||
menu.options['--odirect']['Selected'] = False
|
||||
|
||||
# Done
|
||||
return menu
|
||||
|
||||
|
||||
def disks() -> cli.Menu:
|
||||
"""Disk menu, returns wk.ui.cli.Menu()."""
|
||||
cli.print_info('Scanning disks...')
|
||||
available_disks = get_disks()
|
||||
menu = cli.Menu('ddrescue TUI: Disk selection')
|
||||
menu.disabled_str = 'Already selected'
|
||||
menu.separator = ' '
|
||||
menu.add_action('Quit')
|
||||
for disk in available_disks:
|
||||
menu.add_option(
|
||||
name=(
|
||||
f'{str(disk.path):<12} '
|
||||
f'{disk.bus:<5} '
|
||||
f'{bytes_to_string(disk.size, decimals=1, use_binary=False):<8} '
|
||||
f'{disk.model} '
|
||||
f'{disk.serial}'
|
||||
),
|
||||
details={'Object': disk},
|
||||
)
|
||||
|
||||
# Done
|
||||
return menu
|
||||
|
||||
|
||||
def select_disk(prompt_msg: str, menu: cli.Menu) -> Disk:
|
||||
"""Select disk from provided Menu, returns Disk()."""
|
||||
menu.title = ansi.color_string(
|
||||
f'ddrescue TUI: {prompt_msg} Selection', 'GREEN',
|
||||
)
|
||||
|
||||
# Get selection
|
||||
selection = menu.simple_select()
|
||||
if 'Quit' in selection:
|
||||
raise GenericAbort()
|
||||
|
||||
# Disable selected disk's menu entry
|
||||
menu.options[selection[0]]['Disabled'] = True
|
||||
|
||||
# Update details to include child devices
|
||||
selected_disk = selection[-1]['Object']
|
||||
selected_disk.update_details(skip_children=False)
|
||||
|
||||
# Done
|
||||
return selected_disk
|
||||
|
||||
|
||||
def select_disk_parts(prompt_msg, disk) -> list[Disk]:
|
||||
"""Select disk parts from list, returns list of Disk()."""
|
||||
title = ansi.color_string('ddrescue TUI: Partition Selection', 'GREEN')
|
||||
title += f'\n\nDisk: {disk.path} {disk.description}'
|
||||
menu = cli.Menu(title)
|
||||
menu.separator = ' '
|
||||
menu.add_action('All')
|
||||
menu.add_action('None')
|
||||
menu.add_action('Proceed', {'Separator': True})
|
||||
menu.add_action('Quit')
|
||||
object_list = []
|
||||
|
||||
def _select_parts(menu) -> None:
|
||||
"""Loop over selection menu until at least one partition selected."""
|
||||
while True:
|
||||
selection = menu.advanced_select(
|
||||
f'Please select the parts to {prompt_msg.lower()}: ',
|
||||
)
|
||||
if 'All' in selection:
|
||||
for option in menu.options.values():
|
||||
option['Selected'] = True
|
||||
elif 'None' in selection:
|
||||
for option in menu.options.values():
|
||||
option['Selected'] = False
|
||||
elif 'Proceed' in selection:
|
||||
if any(option['Selected'] for option in menu.options.values()):
|
||||
# At least one partition/device selected/device selected
|
||||
break
|
||||
elif 'Quit' in selection:
|
||||
raise GenericAbort()
|
||||
|
||||
# Bail early if running under macOS
|
||||
if PLATFORM == 'Darwin':
|
||||
return [disk]
|
||||
|
||||
# Bail early if child device selected
|
||||
if disk.parent:
|
||||
return [disk]
|
||||
|
||||
# Add parts
|
||||
whole_disk_str = f'{str(disk.path):<14} (Whole device)'
|
||||
for part in disk.children:
|
||||
fstype = part.get('fstype', '')
|
||||
fstype = str(fstype) if fstype else ''
|
||||
size = part["size"]
|
||||
name = (
|
||||
f'{str(part["path"]):<14} '
|
||||
f'{fstype.upper():<5} '
|
||||
f'({bytes_to_string(size, decimals=1, use_binary=True):>6})'
|
||||
)
|
||||
menu.add_option(name, details={'Selected': True, 'pathlib.Path': part['path']})
|
||||
|
||||
# Add whole disk if necessary
|
||||
if not menu.options:
|
||||
menu.add_option(whole_disk_str, {'Selected': True, 'pathlib.Path': disk.path})
|
||||
menu.title += '\n\n'
|
||||
menu.title += ansi.color_string(' No partitions detected.', 'YELLOW')
|
||||
|
||||
# Get selection
|
||||
_select_parts(menu)
|
||||
|
||||
# Build list of Disk() object_list
|
||||
for option in menu.options.values():
|
||||
if option['Selected']:
|
||||
object_list.append(option['pathlib.Path'])
|
||||
|
||||
# Check if whole disk selected
|
||||
if len(object_list) == len(disk.children):
|
||||
# NOTE: This is not true if the disk has no partitions
|
||||
msg = f'Preserve partition table and unused space in {prompt_msg.lower()}?'
|
||||
if cli.ask(msg):
|
||||
# Replace part list with whole disk obj
|
||||
object_list = [disk.path]
|
||||
|
||||
# Convert object_list to Disk() objects
|
||||
cli.print_standard(' ')
|
||||
cli.print_info('Getting disk/partition details...')
|
||||
object_list = [Disk(path) for path in object_list]
|
||||
|
||||
# Done
|
||||
return object_list
|
||||
|
||||
|
||||
def select_path(prompt_msg) -> pathlib.Path:
|
||||
"""Select path, returns pathlib.Path."""
|
||||
invalid = False
|
||||
menu = cli.Menu(
|
||||
title=ansi.color_string(f'ddrescue TUI: {prompt_msg} Path Selection', 'GREEN'),
|
||||
)
|
||||
menu.separator = ' '
|
||||
menu.add_action('Quit')
|
||||
menu.add_option('Current directory')
|
||||
menu.add_option('Enter manually')
|
||||
path = pathlib.Path.cwd()
|
||||
|
||||
# Make selection
|
||||
selection = menu.simple_select()
|
||||
if 'Current directory' in selection:
|
||||
pass
|
||||
elif 'Enter manually' in selection:
|
||||
path = pathlib.Path(cli.input_text('Please enter path: '))
|
||||
elif 'Quit' in selection:
|
||||
raise GenericAbort()
|
||||
|
||||
# Check
|
||||
try:
|
||||
path = path.resolve()
|
||||
except TypeError:
|
||||
invalid = True
|
||||
if invalid or not path.is_dir():
|
||||
cli.print_error(f'Invalid path: {path}')
|
||||
raise GenericAbort()
|
||||
|
||||
# Done
|
||||
return path
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("This file is not meant to be called directly.")
|
||||
1068
scripts/wk/clone/state.py
Normal file
1068
scripts/wk/clone/state.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -9,7 +9,7 @@ import re
|
|||
import subprocess
|
||||
import time
|
||||
|
||||
from io import BufferedReader, TextIOWrapper
|
||||
from io import IOBase
|
||||
from queue import Queue, Empty
|
||||
from threading import Thread
|
||||
from typing import Any, Callable, Iterable
|
||||
|
|
@ -28,11 +28,11 @@ class NonBlockingStreamReader():
|
|||
## https://gist.github.com/EyalAr/7915597
|
||||
## https://stackoverflow.com/a/4896288
|
||||
|
||||
def __init__(self, stream: BufferedReader | TextIOWrapper):
|
||||
self.stream: BufferedReader | TextIOWrapper = stream
|
||||
def __init__(self, stream: IOBase):
|
||||
self.stream: IOBase = stream
|
||||
self.queue: Queue = Queue()
|
||||
|
||||
def populate_queue(stream: BufferedReader | TextIOWrapper, queue: Queue) -> None:
|
||||
def populate_queue(stream: IOBase, queue: Queue) -> None:
|
||||
"""Collect lines from stream and put them in queue."""
|
||||
while not stream.closed:
|
||||
try:
|
||||
|
|
@ -256,8 +256,9 @@ def run_program(
|
|||
pipe=pipe,
|
||||
shell=shell,
|
||||
**kwargs)
|
||||
check = cmd_kwargs.pop('check', True) # Avoids linting warning
|
||||
try:
|
||||
proc = subprocess.run(**cmd_kwargs)
|
||||
proc = subprocess.run(check=check, **cmd_kwargs)
|
||||
except FileNotFoundError:
|
||||
LOG.error('Command not found: %s', cmd)
|
||||
raise
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import subprocess
|
|||
from typing import TextIO
|
||||
|
||||
from wk import exe
|
||||
from wk.cfg.hw import CPU_FAILURE_TEMP
|
||||
from wk.cfg.hw import CPU_TEMPS
|
||||
from wk.os.mac import set_fans as macos_set_fans
|
||||
from wk.std import PLATFORM
|
||||
from wk.ui import ansi
|
||||
|
|
@ -20,32 +20,75 @@ SysbenchType = tuple[subprocess.Popen, TextIO]
|
|||
|
||||
|
||||
# Functions
|
||||
def check_cooling_results(test_obj, sensors, run_sysbench=False) -> None:
|
||||
"""Check cooling results and update test_obj."""
|
||||
max_temp = sensors.cpu_max_temp()
|
||||
temp_labels = ['Idle', 'Max', 'Cooldown']
|
||||
if run_sysbench:
|
||||
temp_labels.append('Sysbench')
|
||||
def check_cooling_results(sensors, test_object) -> None:
|
||||
"""Check cooling result via sensor data."""
|
||||
idle_temp = sensors.get_cpu_temp('Idle')
|
||||
cooldown_temp = sensors.get_cpu_temp('Cooldown')
|
||||
max_temp = sensors.get_cpu_temp('Max')
|
||||
test_object.report.append(ansi.color_string('Temps', 'BLUE'))
|
||||
|
||||
# Check temps
|
||||
if not max_temp:
|
||||
test_obj.set_status('Unknown')
|
||||
elif max_temp >= CPU_FAILURE_TEMP:
|
||||
test_obj.failed = True
|
||||
test_obj.set_status('Failed')
|
||||
elif 'Aborted' not in test_obj.status:
|
||||
test_obj.passed = True
|
||||
test_obj.set_status('Passed')
|
||||
if max_temp > CPU_TEMPS['Critical']:
|
||||
test_object.failed = True
|
||||
test_object.set_status('Failed')
|
||||
test_object.report.extend([
|
||||
ansi.color_string(
|
||||
f' WARNING: Critical CPU temp of {CPU_TEMPS["Critical"]} exceeded.',
|
||||
'RED',
|
||||
),
|
||||
'',
|
||||
])
|
||||
elif idle_temp >= CPU_TEMPS['Idle High']:
|
||||
test_object.failed = True
|
||||
test_object.set_status('Failed')
|
||||
test_object.report.extend([
|
||||
ansi.color_string(
|
||||
f' WARNING: Max idle temp of {CPU_TEMPS["Idle High"]} exceeded.',
|
||||
'YELLOW',
|
||||
),
|
||||
'',
|
||||
])
|
||||
elif (
|
||||
cooldown_temp <= CPU_TEMPS['Cooling Low Cutoff']
|
||||
or max_temp - cooldown_temp >= CPU_TEMPS['Cooling Delta']
|
||||
):
|
||||
test_object.passed = True
|
||||
test_object.set_status('Passed')
|
||||
else:
|
||||
test_object.passed = False
|
||||
test_object.set_status('Unknown')
|
||||
if cooldown_temp - idle_temp >= CPU_TEMPS['Idle Delta']:
|
||||
test_object.report.extend([
|
||||
ansi.color_string(
|
||||
f' WARNING: Cooldown temp at least {CPU_TEMPS["Idle Delta"]}° over idle.',
|
||||
'YELLOW',
|
||||
),
|
||||
'',
|
||||
])
|
||||
|
||||
# Add temps to report
|
||||
for line in sensors.generate_report(*temp_labels, only_cpu=True):
|
||||
test_obj.report.append(f' {line}')
|
||||
# Build report
|
||||
report_labels = ['Idle']
|
||||
average_labels = []
|
||||
if 'Sysbench' in sensors.temp_labels:
|
||||
average_labels.append('Sysbench')
|
||||
report_labels.extend(['Sysbench', 'Cooldown'])
|
||||
if 'Prime95' in sensors.temp_labels:
|
||||
average_labels.append('Prime95')
|
||||
report_labels.append('Prime95')
|
||||
if 'Cooldown' not in report_labels:
|
||||
report_labels.append('Cooldown')
|
||||
if len(sensors.temp_labels.intersection(['Prime95', 'Sysbench'])) < 1:
|
||||
# Include overall max temp if needed
|
||||
report_labels.append('Max')
|
||||
for line in sensors.generate_report(
|
||||
*report_labels, only_cpu=True, include_avg_for=average_labels):
|
||||
test_object.report.append(f' {line}')
|
||||
|
||||
|
||||
def check_mprime_results(test_obj, working_dir) -> None:
|
||||
"""Check mprime log files and update test_obj."""
|
||||
passing_lines = {}
|
||||
warning_lines = {}
|
||||
passing_lines = set()
|
||||
warning_lines = set()
|
||||
|
||||
def _read_file(log_name) -> list[str]:
|
||||
"""Read file and split into lines, returns list."""
|
||||
|
|
@ -63,7 +106,7 @@ def check_mprime_results(test_obj, working_dir) -> None:
|
|||
for line in _read_file('results.txt'):
|
||||
line = line.strip()
|
||||
if re.search(r'(error|fail)', line, re.IGNORECASE):
|
||||
warning_lines[line] = None
|
||||
warning_lines.add(line)
|
||||
|
||||
# prime.log (check if passed)
|
||||
for line in _read_file('prime.log'):
|
||||
|
|
@ -73,10 +116,10 @@ def check_mprime_results(test_obj, working_dir) -> None:
|
|||
if match:
|
||||
if int(match.group(2)) + int(match.group(3)) > 0:
|
||||
# Errors and/or warnings encountered
|
||||
warning_lines[match.group(1).capitalize()] = None
|
||||
warning_lines.add(match.group(1).capitalize())
|
||||
else:
|
||||
# No errors/warnings
|
||||
passing_lines[match.group(1).capitalize()] = None
|
||||
passing_lines.add(match.group(1).capitalize())
|
||||
|
||||
# Update status
|
||||
if warning_lines:
|
||||
|
|
@ -112,9 +155,11 @@ def start_mprime(working_dir, log_path) -> subprocess.Popen:
|
|||
stdout=subprocess.PIPE,
|
||||
)
|
||||
proc_mprime.stdout.close() # type: ignore[reportOptionalMemberAccess]
|
||||
save_nsbr = exe.NonBlockingStreamReader(proc_grep.stdout)
|
||||
save_nbsr = exe.NonBlockingStreamReader(
|
||||
proc_grep.stdout, # type: ignore[reportGeneralTypeIssues]
|
||||
)
|
||||
exe.start_thread(
|
||||
save_nsbr.save_to_file,
|
||||
save_nbsr.save_to_file,
|
||||
args=(proc_grep, log_path),
|
||||
)
|
||||
|
||||
|
|
@ -122,35 +167,6 @@ def start_mprime(working_dir, log_path) -> subprocess.Popen:
|
|||
return proc_mprime
|
||||
|
||||
|
||||
def start_sysbench(sensors, sensors_out, log_path) -> SysbenchType:
|
||||
"""Start sysbench, returns tuple with Popen object and file handle."""
|
||||
set_apple_fan_speed('max')
|
||||
sysbench_cmd = [
|
||||
'sysbench',
|
||||
f'--threads={exe.psutil.cpu_count()}',
|
||||
'--cpu-max-prime=1000000000',
|
||||
'cpu',
|
||||
'run',
|
||||
]
|
||||
|
||||
# Restart background monitor for Sysbench
|
||||
sensors.stop_background_monitor()
|
||||
sensors.start_background_monitor(
|
||||
sensors_out,
|
||||
alt_max='Sysbench',
|
||||
thermal_action=('killall', 'sysbench', '-INT'),
|
||||
)
|
||||
|
||||
# Start sysbench
|
||||
filehandle_sysbench = open(
|
||||
log_path, 'a', encoding='utf-8',
|
||||
)
|
||||
proc_sysbench = exe.popen_program(sysbench_cmd, stdout=filehandle_sysbench)
|
||||
|
||||
# Done
|
||||
return (proc_sysbench, filehandle_sysbench)
|
||||
|
||||
|
||||
def set_apple_fan_speed(speed) -> None:
|
||||
"""Set Apple fan speed."""
|
||||
cmd = None
|
||||
|
|
@ -174,6 +190,27 @@ def set_apple_fan_speed(speed) -> None:
|
|||
exe.run_program(cmd, check=False)
|
||||
|
||||
|
||||
def start_sysbench(log_path) -> SysbenchType:
|
||||
"""Start sysbench, returns tuple with Popen object and file handle."""
|
||||
set_apple_fan_speed('max')
|
||||
cmd = [
|
||||
'sysbench',
|
||||
f'--threads={exe.psutil.cpu_count()}',
|
||||
'--cpu-max-prime=1000000000',
|
||||
'cpu',
|
||||
'run',
|
||||
]
|
||||
|
||||
# Start sysbench
|
||||
filehandle = open(
|
||||
log_path, 'a', encoding='utf-8',
|
||||
)
|
||||
proc = exe.popen_program(cmd, stdout=filehandle)
|
||||
|
||||
# Done
|
||||
return (proc, filehandle)
|
||||
|
||||
|
||||
def stop_mprime(proc_mprime) -> None:
|
||||
"""Stop mprime gracefully, then forcefully as needed."""
|
||||
proc_mprime.terminate()
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
"""WizardKit: Hardware diagnostics"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
import argparse
|
||||
import atexit
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from docopt import docopt
|
||||
|
||||
from wk import cfg, debug, exe, log, std
|
||||
from wk.cfg.hw import STATUS_COLORS
|
||||
|
|
@ -29,23 +27,13 @@ from wk.ui import ansi, cli, tui
|
|||
|
||||
|
||||
# STATIC VARIABLES
|
||||
DOCSTRING = f'''{cfg.main.KIT_NAME_FULL}: Hardware Diagnostics
|
||||
|
||||
Usage:
|
||||
hw-diags [options]
|
||||
hw-diags (-h | --help)
|
||||
|
||||
Options:
|
||||
-c --cli Force CLI mode
|
||||
-h --help Show this page
|
||||
-q --quick Skip menu and perform a quick check
|
||||
-t --test-mode Run diags in test mode
|
||||
'''
|
||||
LOG = logging.getLogger(__name__)
|
||||
TEST_GROUPS = {
|
||||
# Also used to build the menu options
|
||||
## NOTE: This needs to be above MENU_SETS
|
||||
'CPU & Cooling': 'cpu_stress_tests',
|
||||
'CPU (Sysbench)': 'cpu_test_sysbench',
|
||||
'CPU (Prime95)': 'cpu_test_mprime',
|
||||
'CPU (Cooling)': 'cpu_test_cooling',
|
||||
'Disk Attributes': 'disk_attribute_check',
|
||||
'Disk Self-Test': 'disk_self_test',
|
||||
'Disk Surface Scan': 'disk_surface_scan',
|
||||
|
|
@ -65,6 +53,7 @@ MENU_ACTIONS_SECRET = (
|
|||
MENU_OPTIONS_QUICK = ('Disk Attributes',)
|
||||
MENU_SETS = {
|
||||
'Full Diagnostic': (*TEST_GROUPS,),
|
||||
'CPU Diagnostic': (*[group for group in TEST_GROUPS if group.startswith('CPU')],),
|
||||
'Disk Diagnostic': (
|
||||
'Disk Attributes',
|
||||
'Disk Self-Test',
|
||||
|
|
@ -85,6 +74,7 @@ class State():
|
|||
self.disks: list[hw_disk.Disk] = []
|
||||
self.log_dir: pathlib.Path | None = None
|
||||
self.progress_file: pathlib.Path | None = None
|
||||
self.sensors: hw_sensors.Sensors = hw_sensors.Sensors()
|
||||
self.system: hw_system.System | None = None
|
||||
self.test_groups: list[TestGroup] = []
|
||||
self.title_text: str = ansi.color_string('Hardware Diagnostics', 'GREEN')
|
||||
|
|
@ -100,8 +90,7 @@ class State():
|
|||
test.set_status('Aborted')
|
||||
|
||||
# Cleanup panes
|
||||
self.ui.remove_all_info_panes()
|
||||
self.ui.remove_all_worker_panes()
|
||||
self.reset_layout()
|
||||
|
||||
def disk_safety_checks(self) -> None:
|
||||
"""Check for mid-run SMART failures and failed test(s)."""
|
||||
|
|
@ -123,20 +112,21 @@ class State():
|
|||
|
||||
# Reset objects
|
||||
self.disks.clear()
|
||||
self.sensors = hw_sensors.Sensors()
|
||||
self.test_groups.clear()
|
||||
|
||||
# Set log
|
||||
self.log_dir = log.format_log_path()
|
||||
self.log_dir = pathlib.Path(
|
||||
f'{self.log_dir.parent}/'
|
||||
f'Hardware-Diagnostics_{time.strftime("%Y-%m-%d_%H%M%S%z")}/'
|
||||
self.log_dir = log.format_log_path(
|
||||
log_name='main',
|
||||
sub_dir='Hardware-Diagnostics',
|
||||
)
|
||||
log.update_log_path(
|
||||
dest_dir=self.log_dir,
|
||||
dest_name='main',
|
||||
dest_dir=self.log_dir.parent,
|
||||
dest_name=self.log_dir.stem,
|
||||
keep_history=False,
|
||||
timestamp=False,
|
||||
)
|
||||
self.log_dir = self.log_dir.parent
|
||||
cli.clear_screen()
|
||||
cli.print_info('Initializing...')
|
||||
|
||||
|
|
@ -159,21 +149,9 @@ class State():
|
|||
continue
|
||||
|
||||
if 'CPU' in name:
|
||||
# Create two Test objects which will both be used by cpu_stress_tests
|
||||
# NOTE: Prime95 should be added first
|
||||
self.system.tests.append(
|
||||
Test(dev=self.system, label='Prime95', name=name),
|
||||
)
|
||||
self.system.tests.append(
|
||||
Test(dev=self.system, label='Cooling', name=name),
|
||||
)
|
||||
self.test_groups.append(
|
||||
TestGroup(
|
||||
name=name,
|
||||
function=globals()[TEST_GROUPS[name]],
|
||||
test_objects=self.system.tests,
|
||||
),
|
||||
)
|
||||
Test(dev=self.system, label=name[5:-1], name=name),
|
||||
)
|
||||
|
||||
if 'Disk' in name:
|
||||
test_group = TestGroup(
|
||||
|
|
@ -185,6 +163,23 @@ class State():
|
|||
test_group.test_objects.append(test_obj)
|
||||
self.test_groups.append(test_group)
|
||||
|
||||
# Group CPU tests
|
||||
if self.system.tests:
|
||||
self.test_groups.insert(
|
||||
0,
|
||||
TestGroup(
|
||||
name='CPU & Cooling',
|
||||
function=run_cpu_tests,
|
||||
test_objects=self.system.tests,
|
||||
),
|
||||
)
|
||||
|
||||
def reset_layout(self) -> None:
|
||||
"""Reset layout to avoid flickering."""
|
||||
self.ui.clear_current_pane_height()
|
||||
self.ui.remove_all_info_panes()
|
||||
self.ui.remove_all_worker_panes()
|
||||
|
||||
def save_debug_reports(self) -> None:
|
||||
"""Save debug reports to disk."""
|
||||
LOG.info('Saving debug reports')
|
||||
|
|
@ -218,7 +213,7 @@ class State():
|
|||
proc = exe.run_program(['smc', '-l'])
|
||||
data.extend(proc.stdout.splitlines())
|
||||
except Exception:
|
||||
LOG.ERROR('Error(s) encountered while exporting SMC data')
|
||||
LOG.error('Error(s) encountered while exporting SMC data')
|
||||
data = [line.strip() for line in data]
|
||||
with open(f'{debug_dir}/smc.data', 'a', encoding='utf-8') as _f:
|
||||
_f.write('\n'.join(data))
|
||||
|
|
@ -256,9 +251,39 @@ class State():
|
|||
|
||||
|
||||
# Functions
|
||||
def argparse_helper() -> dict[str, bool]:
|
||||
"""Helper function to setup and return args, returns dict.
|
||||
|
||||
NOTE: A dict is used to match the legacy code.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='hw-diags',
|
||||
description=f'{cfg.main.KIT_NAME_FULL}: Hardware Diagnostics',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-c', '--cli', action='store_true',
|
||||
help='Force CLI mode',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-q', '--quick', action='store_true',
|
||||
help='Skip menu and perform a quick check',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-t', '--test-mode', action='store_true',
|
||||
help='Run diags in test mode',
|
||||
)
|
||||
args = parser.parse_args()
|
||||
legacy_args = {
|
||||
'--cli': args.cli,
|
||||
'--quick': args.quick,
|
||||
'--test-mode': args.test_mode,
|
||||
}
|
||||
return legacy_args
|
||||
|
||||
|
||||
def build_menu(cli_mode=False, quick_mode=False) -> cli.Menu:
|
||||
"""Build main menu, returns wk.ui.cli.Menu."""
|
||||
menu = cli.Menu(title=None)
|
||||
menu = cli.Menu(title='')
|
||||
|
||||
# Add actions, options, etc
|
||||
for action in MENU_ACTIONS:
|
||||
|
|
@ -275,13 +300,15 @@ def build_menu(cli_mode=False, quick_mode=False) -> cli.Menu:
|
|||
|
||||
# Update default selections for quick mode if necessary
|
||||
if quick_mode:
|
||||
for name in menu.options:
|
||||
for name, details in menu.options.items():
|
||||
# Only select quick option(s)
|
||||
menu.options[name]['Selected'] = name in MENU_OPTIONS_QUICK
|
||||
details['Selected'] = name in MENU_OPTIONS_QUICK
|
||||
|
||||
# Skip CPU tests for TestStations
|
||||
if os.path.exists(cfg.hw.TESTSTATION_FILE):
|
||||
menu.options['CPU & Cooling']['Selected'] = False
|
||||
menu.options['CPU (Sysbench)']['Selected'] = False
|
||||
menu.options['CPU (Prime95)']['Selected'] = False
|
||||
menu.options['CPU (Cooling)']['Selected'] = False
|
||||
|
||||
# Add CLI actions if necessary
|
||||
if cli_mode or 'DISPLAY' not in os.environ:
|
||||
|
|
@ -307,140 +334,213 @@ def build_menu(cli_mode=False, quick_mode=False) -> cli.Menu:
|
|||
return menu
|
||||
|
||||
|
||||
def cpu_stress_tests(state, test_objects, test_mode=False) -> None:
|
||||
"""CPU & cooling check using Prime95 and Sysbench."""
|
||||
LOG.info('CPU Test (Prime95)')
|
||||
aborted = False
|
||||
prime_log = pathlib.Path(f'{state.log_dir}/prime.log')
|
||||
run_sysbench = False
|
||||
def cpu_tests_init(state: State) -> None:
|
||||
"""Initialize CPU tests."""
|
||||
sensors_out = pathlib.Path(f'{state.log_dir}/sensors.out')
|
||||
test_minutes = cfg.hw.CPU_TEST_MINUTES
|
||||
if test_mode:
|
||||
test_minutes = cfg.hw.TEST_MODE_CPU_LIMIT
|
||||
test_mprime_obj, test_cooling_obj = test_objects
|
||||
state.update_title_text(state.system.cpu_description)
|
||||
|
||||
# Bail early
|
||||
if test_cooling_obj.disabled or test_mprime_obj.disabled:
|
||||
return
|
||||
|
||||
# Prep
|
||||
state.update_title_text(test_mprime_obj.dev.cpu_description)
|
||||
test_cooling_obj.set_status('Working')
|
||||
test_mprime_obj.set_status('Working')
|
||||
|
||||
# Start sensors monitor
|
||||
sensors = hw_sensors.Sensors()
|
||||
sensors.start_background_monitor(
|
||||
sensors_out,
|
||||
thermal_action=('killall', 'mprime', '-INT'),
|
||||
)
|
||||
|
||||
# Create monitor and worker panes
|
||||
state.update_progress_file()
|
||||
state.ui.add_worker_pane(lines=10, watch_cmd='tail', watch_file=prime_log)
|
||||
# Start monitor
|
||||
if PLATFORM == 'Darwin':
|
||||
state.ui.add_info_pane(
|
||||
percent=80, cmd='./hw-sensors', update_layout=False,
|
||||
)
|
||||
elif PLATFORM == 'Linux':
|
||||
state.ui.add_info_pane(
|
||||
percent=80, watch_file=sensors_out, update_layout=False,
|
||||
percent=80,
|
||||
watch_file=pathlib.Path(f'{state.log_dir}/sensors.out'),
|
||||
update_layout=False,
|
||||
)
|
||||
state.sensors.start_background_monitor(sensors_out)
|
||||
state.ui.set_current_pane_height(3)
|
||||
|
||||
# Get idle temps
|
||||
# Save idle temps
|
||||
cli.print_standard('Saving idle temps...')
|
||||
sensors.save_average_temps(temp_label='Idle', seconds=5)
|
||||
state.sensors.save_average_temps(temp_label='Idle', seconds=5, save_history=False)
|
||||
|
||||
# Stress CPU
|
||||
cli.print_info('Running stress test')
|
||||
hw_cpu.set_apple_fan_speed('max')
|
||||
proc_mprime = hw_cpu.start_mprime(state.log_dir, prime_log)
|
||||
|
||||
# Show countdown
|
||||
print('')
|
||||
try:
|
||||
print_countdown(proc=proc_mprime, seconds=test_minutes*60)
|
||||
except KeyboardInterrupt:
|
||||
aborted = True
|
||||
|
||||
# Stop Prime95
|
||||
hw_cpu.stop_mprime(proc_mprime)
|
||||
|
||||
# Update progress if necessary
|
||||
if sensors.cpu_reached_critical_temp() or aborted:
|
||||
test_cooling_obj.set_status('Aborted')
|
||||
test_mprime_obj.set_status('Aborted')
|
||||
state.update_progress_file()
|
||||
|
||||
# Get cooldown temp
|
||||
state.ui.clear_current_pane()
|
||||
cli.print_standard('Letting CPU cooldown...')
|
||||
std.sleep(5)
|
||||
cli.print_standard('Saving cooldown temps...')
|
||||
sensors.save_average_temps(temp_label='Cooldown', seconds=5)
|
||||
|
||||
# Check Prime95 results
|
||||
test_mprime_obj.report.append(ansi.color_string('Prime95', 'BLUE'))
|
||||
hw_cpu.check_mprime_results(
|
||||
test_obj=test_mprime_obj, working_dir=state.log_dir,
|
||||
)
|
||||
|
||||
# Run Sysbench test if necessary
|
||||
run_sysbench = (
|
||||
not aborted and sensors.cpu_max_temp() >= cfg.hw.CPU_FAILURE_TEMP
|
||||
)
|
||||
if run_sysbench:
|
||||
LOG.info('CPU Test (Sysbench)')
|
||||
cli.print_standard('Letting CPU cooldown more...')
|
||||
std.sleep(10)
|
||||
state.ui.clear_current_pane()
|
||||
cli.print_info('Running alternate stress test')
|
||||
print('')
|
||||
sysbench_log = prime_log.with_name('sysbench.log')
|
||||
sysbench_log.touch()
|
||||
state.ui.remove_all_worker_panes()
|
||||
state.ui.add_worker_pane(lines=10, watch_cmd='tail', watch_file=sysbench_log)
|
||||
proc_sysbench, filehandle_sysbench = hw_cpu.start_sysbench(
|
||||
sensors,
|
||||
sensors_out,
|
||||
log_path=sysbench_log,
|
||||
)
|
||||
try:
|
||||
print_countdown(proc=proc_sysbench, seconds=test_minutes*60)
|
||||
except AttributeError:
|
||||
# Assuming the sysbench process wasn't found and proc was set to None
|
||||
LOG.error('Failed to find sysbench process', exc_info=True)
|
||||
except KeyboardInterrupt:
|
||||
aborted = True
|
||||
hw_cpu.stop_sysbench(proc_sysbench, filehandle_sysbench)
|
||||
|
||||
# Update progress
|
||||
# NOTE: CPU critical temp check isn't really necessary
|
||||
# Hard to imagine it wasn't hit during Prime95 but was in sysbench
|
||||
if sensors.cpu_reached_critical_temp() or aborted:
|
||||
test_cooling_obj.set_status('Aborted')
|
||||
test_mprime_obj.set_status('Aborted')
|
||||
state.update_progress_file()
|
||||
|
||||
# Check Cooling results
|
||||
test_cooling_obj.report.append(ansi.color_string('Temps', 'BLUE'))
|
||||
hw_cpu.check_cooling_results(test_cooling_obj, sensors, run_sysbench)
|
||||
|
||||
def cpu_tests_end(state: State) -> None:
|
||||
"""End CPU tests."""
|
||||
# Cleanup
|
||||
state.update_progress_file()
|
||||
sensors.stop_background_monitor()
|
||||
state.sensors.clear_temps(next_label='Done')
|
||||
state.sensors.stop_background_monitor()
|
||||
state.ui.clear_current_pane_height()
|
||||
state.ui.remove_all_info_panes()
|
||||
state.ui.remove_all_worker_panes()
|
||||
|
||||
|
||||
def cpu_test_cooling(state: State, test_object, test_mode=False) -> None:
|
||||
"""CPU cooling test via sensor data assessment."""
|
||||
_ = test_mode
|
||||
LOG.info('CPU Test (Cooling)')
|
||||
|
||||
# Bail early
|
||||
if test_object.disabled:
|
||||
return
|
||||
|
||||
hw_cpu.check_cooling_results(state.sensors, test_object)
|
||||
state.update_progress_file()
|
||||
|
||||
|
||||
def cpu_test_mprime(state: State, test_object, test_mode=False) -> None:
|
||||
"""CPU stress test using mprime."""
|
||||
LOG.info('CPU Test (Prime95)')
|
||||
aborted = False
|
||||
log_path = pathlib.Path(f'{state.log_dir}/prime.log')
|
||||
sensors_out = pathlib.Path(f'{state.log_dir}/sensors.out')
|
||||
test_minutes = cfg.hw.CPU_TEST_MINUTES
|
||||
if test_mode:
|
||||
test_minutes = cfg.hw.TEST_MODE_CPU_LIMIT
|
||||
|
||||
# Bail early
|
||||
if test_object.disabled:
|
||||
return
|
||||
if state.sensors.cpu_reached_critical_temp():
|
||||
test_object.set_status('Denied')
|
||||
test_object.disabled = True
|
||||
return
|
||||
|
||||
# Prep
|
||||
test_object.set_status('Working')
|
||||
state.update_progress_file()
|
||||
state.ui.clear_current_pane()
|
||||
cli.print_info('Running stress test')
|
||||
print('')
|
||||
|
||||
# Start sensors monitor
|
||||
state.sensors.clear_temps(next_label='Prime95')
|
||||
state.sensors.stop_background_monitor()
|
||||
state.sensors.start_background_monitor(
|
||||
sensors_out,
|
||||
alt_max='Prime95',
|
||||
thermal_action=('killall', '-INT', 'mprime'),
|
||||
)
|
||||
|
||||
# Run Prime95
|
||||
hw_cpu.set_apple_fan_speed('max')
|
||||
proc = hw_cpu.start_mprime(state.log_dir, log_path)
|
||||
state.ui.add_worker_pane(lines=10, watch_cmd='tail', watch_file=log_path)
|
||||
try:
|
||||
print_countdown(proc=proc, seconds=test_minutes*60)
|
||||
except KeyboardInterrupt:
|
||||
aborted = True
|
||||
|
||||
# Stop Prime95
|
||||
hw_cpu.stop_mprime(proc)
|
||||
|
||||
# Get cooldown temp
|
||||
if 'Cooldown' in state.sensors.temp_labels:
|
||||
# Give Prime95 time to save the results
|
||||
std.sleep(1)
|
||||
state.sensors.clear_temps(next_label='Cooldown')
|
||||
else:
|
||||
# Save cooldown temp
|
||||
state.ui.clear_current_pane()
|
||||
cli.print_standard('Letting CPU cooldown...')
|
||||
std.sleep(5)
|
||||
cli.print_standard('Saving cooldown temps...')
|
||||
state.sensors.save_average_temps(temp_label='Cooldown', seconds=5)
|
||||
|
||||
# Check Prime95 results
|
||||
test_object.report.append(ansi.color_string('Prime95', 'BLUE'))
|
||||
hw_cpu.check_mprime_results(test_obj=test_object, working_dir=state.log_dir)
|
||||
|
||||
# Update progress
|
||||
if state.sensors.cpu_reached_critical_temp() or aborted:
|
||||
test_object.set_status('Aborted')
|
||||
state.update_progress_file()
|
||||
|
||||
# Done
|
||||
state.ui.remove_all_worker_panes()
|
||||
if aborted:
|
||||
cpu_tests_end(state)
|
||||
raise std.GenericAbort('Aborted')
|
||||
|
||||
|
||||
def disk_attribute_check(state, test_objects, test_mode=False) -> None:
|
||||
def cpu_test_sysbench(state: State, test_object, test_mode=False) -> None:
|
||||
"""CPU stress test using Sysbench."""
|
||||
LOG.info('CPU Test (Sysbench)')
|
||||
aborted = False
|
||||
log_path = pathlib.Path(f'{state.log_dir}/sysbench.log')
|
||||
sensors_out = pathlib.Path(f'{state.log_dir}/sensors.out')
|
||||
test_minutes = cfg.hw.CPU_TEST_MINUTES
|
||||
if test_mode:
|
||||
test_minutes = cfg.hw.TEST_MODE_CPU_LIMIT
|
||||
|
||||
# Bail early
|
||||
if test_object.disabled:
|
||||
return
|
||||
|
||||
# Prep
|
||||
test_object.set_status('Working')
|
||||
state.update_progress_file()
|
||||
state.ui.clear_current_pane()
|
||||
cli.print_info('Running stress test')
|
||||
print('')
|
||||
|
||||
# Start sensors monitor
|
||||
state.sensors.clear_temps(next_label='Sysbench')
|
||||
state.sensors.stop_background_monitor()
|
||||
state.sensors.start_background_monitor(
|
||||
sensors_out,
|
||||
alt_max='Sysbench',
|
||||
thermal_action=('killall', '-INT', 'sysbench'),
|
||||
)
|
||||
|
||||
# Run sysbench
|
||||
state.ui.add_worker_pane(lines=10, watch_cmd='tail', watch_file=log_path)
|
||||
proc, filehandle = hw_cpu.start_sysbench(log_path=log_path)
|
||||
try:
|
||||
print_countdown(proc=proc, seconds=test_minutes*60)
|
||||
except AttributeError:
|
||||
# Assuming the sysbench process wasn't found and proc was set to None
|
||||
LOG.error('Failed to find sysbench process', exc_info=True)
|
||||
except KeyboardInterrupt:
|
||||
aborted = True
|
||||
hw_cpu.stop_sysbench(proc, filehandle)
|
||||
|
||||
# Get cooldown temp
|
||||
if 'Cooldown' in state.sensors.temp_labels:
|
||||
state.sensors.clear_temps(next_label='Cooldown')
|
||||
else:
|
||||
state.ui.clear_current_pane()
|
||||
cli.print_standard('Letting CPU cooldown...')
|
||||
std.sleep(5)
|
||||
cli.print_standard('Saving cooldown temps...')
|
||||
state.sensors.save_average_temps(temp_label='Cooldown', seconds=5)
|
||||
|
||||
# Update progress
|
||||
test_object.report.append(ansi.color_string('Sysbench', 'BLUE'))
|
||||
if aborted:
|
||||
test_object.set_status('Aborted')
|
||||
test_object.report.append(ansi.color_string(' Aborted.', 'YELLOW'))
|
||||
state.update_progress_file()
|
||||
elif state.sensors.cpu_reached_critical_temp():
|
||||
test_object.set_status('Aborted')
|
||||
test_object.report.append(
|
||||
ansi.color_string(' Aborted due to temps.', 'YELLOW'),
|
||||
)
|
||||
elif proc.returncode not in (-15, -2, 0):
|
||||
# NOTE: Return codes:
|
||||
# 0 == Completed w/out issue
|
||||
# -2 == Stopped with INT signal
|
||||
# -15 == Stopped with TERM signal
|
||||
test_object.set_status('Failed')
|
||||
test_object.report.append(f' Failed with return code: {proc.returncode}')
|
||||
else:
|
||||
test_object.set_status('Passed')
|
||||
test_object.report.append(' Completed without issue.')
|
||||
state.update_progress_file()
|
||||
|
||||
# Done
|
||||
state.ui.remove_all_worker_panes()
|
||||
if aborted:
|
||||
cpu_tests_end(state)
|
||||
raise std.GenericAbort('Aborted')
|
||||
|
||||
|
||||
def disk_attribute_check(state: State, test_objects, test_mode=False) -> None:
|
||||
"""Disk attribute check."""
|
||||
_ = test_mode
|
||||
LOG.info('Disk Attribute Check')
|
||||
for test in test_objects:
|
||||
disk_smart_status_check(test.dev, mid_run=False)
|
||||
|
|
@ -516,8 +616,9 @@ def disk_io_benchmark(
|
|||
raise std.GenericAbort('Aborted')
|
||||
|
||||
|
||||
def disk_self_test(state, test_objects, test_mode=False) -> None:
|
||||
def disk_self_test(state: State, test_objects, test_mode=False) -> None:
|
||||
"""Disk self-test if available."""
|
||||
_ = test_mode
|
||||
LOG.info('Disk Self-Test(s)')
|
||||
aborted = False
|
||||
threads = []
|
||||
|
|
@ -540,7 +641,7 @@ def disk_self_test(state, test_objects, test_mode=False) -> None:
|
|||
|
||||
# Show progress
|
||||
if threads[-1].is_alive():
|
||||
state.ui.add_worker_pane(lines=4, watch_cmd='tail', watch_file=test_log)
|
||||
state.ui.add_worker_pane(lines=4, watch_file=test_log)
|
||||
|
||||
# Wait for all tests to complete
|
||||
state.update_progress_file()
|
||||
|
|
@ -608,7 +709,7 @@ def disk_smart_status_check(dev, mid_run=True) -> None:
|
|||
dev.disable_disk_tests()
|
||||
|
||||
|
||||
def disk_surface_scan(state, test_objects, test_mode=False) -> None:
|
||||
def disk_surface_scan(state: State, test_objects, test_mode=False) -> None:
|
||||
"""Read-only disk surface scan using badblocks."""
|
||||
LOG.info('Disk Surface Scan (badblocks)')
|
||||
aborted = False
|
||||
|
|
@ -664,7 +765,12 @@ def disk_surface_scan(state, test_objects, test_mode=False) -> None:
|
|||
|
||||
def main() -> None:
|
||||
"""Main function for hardware diagnostics."""
|
||||
args = docopt(DOCSTRING)
|
||||
try:
|
||||
args = argparse_helper()
|
||||
except SystemExit:
|
||||
print('')
|
||||
cli.pause('Press Enter to exit...')
|
||||
raise
|
||||
log.update_log_path(dest_name='Hardware-Diagnostics', timestamp=True)
|
||||
|
||||
# Safety check
|
||||
|
|
@ -760,8 +866,18 @@ def print_countdown(proc, seconds) -> None:
|
|||
# Done
|
||||
print('')
|
||||
|
||||
def run_cpu_tests(state: State, test_objects, test_mode=False) -> None:
|
||||
"""Run selected CPU test(s)."""
|
||||
state.update_progress_file()
|
||||
cpu_tests_init(state)
|
||||
for obj in test_objects:
|
||||
func = globals()[TEST_GROUPS[obj.name]]
|
||||
func(state, obj, test_mode=test_mode)
|
||||
cpu_tests_end(state)
|
||||
state.update_progress_file()
|
||||
|
||||
def run_diags(state, menu, quick_mode=False, test_mode=False) -> None:
|
||||
|
||||
def run_diags(state: State, menu, quick_mode=False, test_mode=False) -> None:
|
||||
"""Run selected diagnostics."""
|
||||
aborted = False
|
||||
atexit.register(state.save_debug_reports)
|
||||
|
|
@ -788,6 +904,7 @@ def run_diags(state, menu, quick_mode=False, test_mode=False) -> None:
|
|||
aborted = True
|
||||
state.abort_testing()
|
||||
state.update_progress_file()
|
||||
state.reset_layout()
|
||||
break
|
||||
else:
|
||||
# Run safety checks after disk tests
|
||||
|
|
@ -813,7 +930,7 @@ def run_diags(state, menu, quick_mode=False, test_mode=False) -> None:
|
|||
cli.pause('Press Enter to return to main menu...')
|
||||
|
||||
|
||||
def show_failed_attributes(state) -> None:
|
||||
def show_failed_attributes(state: State) -> None:
|
||||
"""Show failed attributes for all disks."""
|
||||
for dev in state.disks:
|
||||
cli.print_colored([dev.name, dev.description], ['CYAN', None])
|
||||
|
|
@ -823,7 +940,7 @@ def show_failed_attributes(state) -> None:
|
|||
cli.print_standard('')
|
||||
|
||||
|
||||
def show_results(state) -> None:
|
||||
def show_results(state: State) -> None:
|
||||
"""Show test results by device."""
|
||||
std.sleep(0.5)
|
||||
state.ui.clear_current_pane()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""WizardKit: Disk object and functions"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
import copy
|
||||
import logging
|
||||
import pathlib
|
||||
import platform
|
||||
|
|
@ -12,7 +11,6 @@ from dataclasses import dataclass, field
|
|||
from typing import Any
|
||||
|
||||
from wk.cfg.main import KIT_NAME_SHORT
|
||||
from wk.cfg.python import DATACLASS_DECORATOR_KWARGS
|
||||
from wk.exe import get_json_from_command, run_program
|
||||
from wk.hw.test import Test
|
||||
from wk.hw.smart import (
|
||||
|
|
@ -32,7 +30,7 @@ WK_LABEL_REGEX = re.compile(
|
|||
|
||||
|
||||
# Classes
|
||||
@dataclass(**DATACLASS_DECORATOR_KWARGS)
|
||||
@dataclass(slots=True)
|
||||
class Disk:
|
||||
"""Object for tracking disk specific data."""
|
||||
attributes: dict[Any, dict] = field(init=False, default_factory=dict)
|
||||
|
|
@ -40,34 +38,29 @@ class Disk:
|
|||
children: list[dict] = field(init=False, default_factory=list)
|
||||
description: str = field(init=False)
|
||||
filesystem: str = field(init=False)
|
||||
initial_attributes: dict[Any, dict] = field(init=False)
|
||||
initial_attributes: dict[Any, dict] = field(init=False, default_factory=dict)
|
||||
known_attributes: dict[Any, dict] = field(init=False, default_factory=dict)
|
||||
log_sec: int = field(init=False)
|
||||
model: str = field(init=False)
|
||||
name: str = field(init=False)
|
||||
notes: list[str] = field(init=False, default_factory=list)
|
||||
path: pathlib.Path | str
|
||||
path: pathlib.Path = field(init=False)
|
||||
path_str: pathlib.Path | str
|
||||
parent: str = field(init=False)
|
||||
phy_sec: int = field(init=False)
|
||||
raw_details: dict[str, Any] = field(init=False)
|
||||
raw_smartctl: dict[str, Any] = field(init=False)
|
||||
raw_smartctl: dict[str, Any] = field(init=False, default_factory=dict)
|
||||
serial: str = field(init=False)
|
||||
size: int = field(init=False)
|
||||
ssd: bool = field(init=False)
|
||||
tests: list[Test] = field(init=False, default_factory=list)
|
||||
use_sat: bool = field(init=False, default=False)
|
||||
trim: bool = field(init=False)
|
||||
|
||||
def __post_init__(self):
|
||||
self.path = pathlib.Path(self.path).resolve()
|
||||
self.path = pathlib.Path(self.path_str).resolve()
|
||||
self.update_details()
|
||||
self.set_description()
|
||||
self.known_attributes = get_known_disk_attributes(self.model)
|
||||
if not self.attributes and self.bus == 'USB':
|
||||
# Try using SAT
|
||||
LOG.warning('Using SAT for smartctl for %s', self.path)
|
||||
self.notes = []
|
||||
self.use_sat = True
|
||||
self.initial_attributes = copy.deepcopy(self.attributes)
|
||||
if not self.is_4k_aligned():
|
||||
self.add_note('One or more partitions are not 4K aligned', 'YELLOW')
|
||||
|
||||
|
|
@ -212,6 +205,7 @@ class Disk:
|
|||
self.serial = self.raw_details.get('serial', 'Unknown Serial')
|
||||
self.size = self.raw_details.get('size', -1)
|
||||
self.ssd = self.raw_details.get('ssd', False)
|
||||
self.trim = self.raw_details.get('trim', False)
|
||||
|
||||
# Ensure certain attributes types
|
||||
## NOTE: This is ugly, deal.
|
||||
|
|
@ -225,6 +219,10 @@ class Disk:
|
|||
if attr == 'size':
|
||||
setattr(self, attr, -1)
|
||||
|
||||
# Add TRIM note
|
||||
if self.trim:
|
||||
self.add_note('TRIM support detected', 'YELLOW')
|
||||
|
||||
|
||||
# Functions
|
||||
def get_disk_details_linux(disk_path, skip_children=True) -> dict[Any, Any]:
|
||||
|
|
@ -248,10 +246,12 @@ def get_disk_details_linux(disk_path, skip_children=True) -> dict[Any, Any]:
|
|||
dev['bus'] = dev.pop('tran', '???')
|
||||
dev['parent'] = dev.pop('pkname', None)
|
||||
dev['ssd'] = not dev.pop('rota', True)
|
||||
dev['trim'] = bool(dev.pop('disc-max', 0))
|
||||
if 'loop' in str(disk_path) and dev['bus'] is None:
|
||||
dev['bus'] = 'Image'
|
||||
dev['model'] = ''
|
||||
dev['serial'] = ''
|
||||
dev['trim'] = False # NOTE: This check is just for physical devices
|
||||
|
||||
# Convert to dict
|
||||
details = dev_list.pop(0)
|
||||
|
|
@ -309,6 +309,7 @@ def get_disk_details_macos(disk_path, skip_children=True) -> dict:
|
|||
dev['serial'] = get_disk_serial_macos(dev['path'])
|
||||
dev['size'] = dev.pop('Size', -1)
|
||||
dev['ssd'] = dev.pop('SolidState', False)
|
||||
dev['trim'] = False # TODO: ACtually check for TRIM
|
||||
dev['vendor'] = ''
|
||||
if dev.get('WholeDisk', True):
|
||||
dev['parent'] = None
|
||||
|
|
|
|||
|
|
@ -6,11 +6,12 @@ import logging
|
|||
import pathlib
|
||||
import re
|
||||
|
||||
from copy import deepcopy
|
||||
from subprocess import CalledProcessError
|
||||
from threading import Thread
|
||||
from typing import Any
|
||||
|
||||
from wk.cfg.hw import CPU_CRITICAL_TEMP, SMC_IDS, TEMP_COLORS
|
||||
from wk.cfg.hw import CPU_TEMPS, SMC_IDS, TEMP_COLORS
|
||||
from wk.exe import run_program, start_thread
|
||||
from wk.io import non_clobber_path
|
||||
from wk.std import PLATFORM, sleep
|
||||
|
|
@ -36,39 +37,83 @@ class ThermalLimitReachedError(RuntimeError):
|
|||
|
||||
# Classes
|
||||
class Sensors():
|
||||
"""Class for holding sensor specific data."""
|
||||
"""Class for holding sensor specific data.
|
||||
|
||||
# Sensor data structure
|
||||
#
|
||||
# Section # CPUTemps / Other
|
||||
# Adapters # coretemp / acpi / nvme / etc
|
||||
# Sources # Core 1 / SODIMM / Sensor X / etc
|
||||
# Label # temp1_input / etc (i.e. lm_sensor label)
|
||||
# Max # 99.0
|
||||
# X # 55.0 (where X is Idle/Current/Sysbench/etc)
|
||||
# Temps # [39.0, 38.0, 40.0, 39.0, 38.0, ...]
|
||||
#
|
||||
# e.g.
|
||||
# { 'CPUTemps': { 'coretemp-isa-0000': { 'Core 0': { 'Average': 44.5,
|
||||
# 'Current': 44.0,
|
||||
# 'Idle': 44.5,
|
||||
# 'Label': 'temp2_input',
|
||||
# 'Max': 45.0,
|
||||
# 'Temps': [ 45.0,
|
||||
# 45.0,
|
||||
# ...,
|
||||
# 42.0]}}}}
|
||||
#
|
||||
# Sensor history data structure
|
||||
# [ ('Name of "run"', sensor_data_structure_described_above), ]
|
||||
#
|
||||
# e.g.
|
||||
# [
|
||||
# ( 'Idle',
|
||||
# { 'CPUTemps': { 'coretemp-isa-0000': { 'Core 0': { 'Max': 45.0, ..., }}}}
|
||||
# ),
|
||||
# ( 'Sysbench',
|
||||
# { 'CPUTemps': { 'coretemp-isa-0000': { 'Core 0': { 'Max': 85.0, ..., }}}}
|
||||
# ),
|
||||
# ]
|
||||
"""
|
||||
def __init__(self):
|
||||
self.background_thread: Thread | None = None
|
||||
self.data: dict[Any, Any] = get_sensor_data()
|
||||
self.history: list[tuple[str, dict]] = []
|
||||
self.history_index: dict[str, int] = {}
|
||||
self.history_next_label: str = 'Idle'
|
||||
self.out_path: pathlib.Path | str | None = None
|
||||
self.temp_labels: set = set(['Current', 'Max'])
|
||||
|
||||
def clear_temps(self) -> None:
|
||||
def clear_temps(self, next_label: str, save_history: bool = True) -> None:
|
||||
"""Clear saved temps but keep structure"""
|
||||
prev_label = self.history_next_label
|
||||
self.history_next_label = next_label
|
||||
|
||||
# Save history
|
||||
if save_history:
|
||||
cur_data = deepcopy(self.data)
|
||||
|
||||
# Calculate averages
|
||||
for adapters in cur_data.values():
|
||||
for sources in adapters.values():
|
||||
for name in sources:
|
||||
temp_list = sources[name]['Temps']
|
||||
try:
|
||||
sources[name]['Average'] = sum(temp_list) / len(temp_list)
|
||||
except ZeroDivisionError:
|
||||
LOG.error('Failed to calculate averate temp for %s', name)
|
||||
sources[name]['Average'] = 0
|
||||
|
||||
# Add to history
|
||||
self.history.append((prev_label, cur_data))
|
||||
self.history_index[prev_label] = len(self.history) - 1
|
||||
|
||||
# Clear data
|
||||
for adapters in self.data.values():
|
||||
for sources in adapters.values():
|
||||
for source_data in sources.values():
|
||||
source_data['Temps'] = []
|
||||
|
||||
def cpu_max_temp(self) -> float:
|
||||
"""Get max temp from any CPU source, returns float.
|
||||
|
||||
NOTE: If no temps are found this returns zero.
|
||||
"""
|
||||
max_temp = 0.0
|
||||
|
||||
# Check all CPU Temps
|
||||
for section, adapters in self.data.items():
|
||||
if not section.startswith('CPU'):
|
||||
continue
|
||||
for sources in adapters.values():
|
||||
for source_data in sources.values():
|
||||
max_temp = max(max_temp, source_data.get('Max', 0))
|
||||
|
||||
# Done
|
||||
return max_temp
|
||||
|
||||
def cpu_reached_critical_temp(self) -> bool:
|
||||
"""Check if CPU reached CPU_CRITICAL_TEMP, returns bool."""
|
||||
"""Check if CPU exceeded critical temp, returns bool."""
|
||||
for section, adapters in self.data.items():
|
||||
if not section.startswith('CPU'):
|
||||
# Limit to CPU temps
|
||||
|
|
@ -77,16 +122,22 @@ class Sensors():
|
|||
# Ugly section
|
||||
for sources in adapters.values():
|
||||
for source_data in sources.values():
|
||||
if source_data.get('Max', -1) >= CPU_CRITICAL_TEMP:
|
||||
if source_data.get('Max', -1) > CPU_TEMPS['Critical']:
|
||||
return True
|
||||
|
||||
# Didn't return above so temps are within the threshold
|
||||
return False
|
||||
|
||||
def generate_report(
|
||||
self, *temp_labels, colored=True, only_cpu=False) -> list[str]:
|
||||
self,
|
||||
*temp_labels: str,
|
||||
colored: bool = True,
|
||||
only_cpu: bool = False,
|
||||
include_avg_for: list[str] | None = None,
|
||||
) -> list[str]:
|
||||
"""Generate report based on given temp_labels, returns list."""
|
||||
report = []
|
||||
include_avg_for = include_avg_for if include_avg_for else []
|
||||
|
||||
for section, adapters in sorted(self.data.items()):
|
||||
if only_cpu and not section.startswith('CPU'):
|
||||
|
|
@ -100,6 +151,10 @@ class Sensors():
|
|||
for label in temp_labels:
|
||||
if label != 'Current':
|
||||
line += f' {label.lower()}: '
|
||||
if label in include_avg_for:
|
||||
avg_temp = self.get_avg_temp(
|
||||
label, section, adapter, source, colored)
|
||||
line += f'{avg_temp} / '
|
||||
line += get_temp_str(
|
||||
source_data.get(label, '???'),
|
||||
colored=colored,
|
||||
|
|
@ -119,6 +174,32 @@ class Sensors():
|
|||
# Done
|
||||
return report
|
||||
|
||||
def get_avg_temp(self, label, section, adapter, source, colored) -> str:
|
||||
"""Get average temp from history, return str."""
|
||||
# NOTE: This is Super-ugly
|
||||
label_index = self.history_index[label]
|
||||
avg_temp = self.history[label_index][1][section][adapter][source]['Average']
|
||||
return get_temp_str(avg_temp, colored=colored)
|
||||
|
||||
def get_cpu_temp(self, label) -> float:
|
||||
"""Get temp for label from any CPU source, returns float.
|
||||
|
||||
NOTE: This returns the highest value for the label.
|
||||
NOTE 2: If no temps are found this returns zero.
|
||||
"""
|
||||
max_temp = 0.0
|
||||
|
||||
# Check all CPU Temps
|
||||
for section, adapters in self.data.items():
|
||||
if not section.startswith('CPU'):
|
||||
continue
|
||||
for sources in adapters.values():
|
||||
for source_data in sources.values():
|
||||
max_temp = max(max_temp, source_data.get(label, 0))
|
||||
|
||||
# Done
|
||||
return float(max_temp)
|
||||
|
||||
def monitor_to_file(
|
||||
self, out_path, alt_max=None,
|
||||
exit_on_thermal_limit=True, temp_labels=None,
|
||||
|
|
@ -136,6 +217,7 @@ class Sensors():
|
|||
temp_labels = ['Current', 'Max']
|
||||
if alt_max:
|
||||
temp_labels.append(alt_max)
|
||||
self.temp_labels.add(alt_max)
|
||||
|
||||
# Start loop
|
||||
while True:
|
||||
|
|
@ -155,9 +237,15 @@ class Sensors():
|
|||
# Sleep before next loop
|
||||
sleep(0.5)
|
||||
|
||||
def save_average_temps(self, temp_label, seconds=10) -> None:
|
||||
def save_average_temps(
|
||||
self,
|
||||
temp_label: str,
|
||||
seconds: int = 10,
|
||||
save_history: bool = True,
|
||||
) -> None:
|
||||
"""Save average temps under temp_label over provided seconds.."""
|
||||
self.clear_temps()
|
||||
self.clear_temps(next_label=temp_label, save_history=save_history)
|
||||
self.temp_labels.add(temp_label)
|
||||
|
||||
# Get temps
|
||||
for _ in range(seconds):
|
||||
|
|
@ -200,6 +288,10 @@ class Sensors():
|
|||
|
||||
def stop_background_monitor(self) -> None:
|
||||
"""Stop background thread."""
|
||||
# Bail early
|
||||
if self.background_thread is None:
|
||||
return
|
||||
|
||||
self.out_path.with_suffix('.stop').touch()
|
||||
self.background_thread.join()
|
||||
|
||||
|
|
@ -210,6 +302,8 @@ class Sensors():
|
|||
def update_sensor_data(
|
||||
self, alt_max=None, exit_on_thermal_limit=True) -> None:
|
||||
"""Update sensor data via OS-specific means."""
|
||||
if alt_max:
|
||||
self.temp_labels.add(alt_max)
|
||||
if PLATFORM == 'Darwin':
|
||||
self.update_sensor_data_macos(alt_max, exit_on_thermal_limit)
|
||||
elif PLATFORM == 'Linux':
|
||||
|
|
@ -236,7 +330,7 @@ class Sensors():
|
|||
|
||||
# Raise exception if thermal limit reached
|
||||
if exit_on_thermal_limit and section == 'CPUTemps':
|
||||
if source_data['Current'] >= CPU_CRITICAL_TEMP:
|
||||
if source_data['Current'] > CPU_TEMPS['Critical']:
|
||||
raise ThermalLimitReachedError('CPU temps reached limit')
|
||||
|
||||
def update_sensor_data_macos(
|
||||
|
|
@ -263,7 +357,7 @@ class Sensors():
|
|||
|
||||
# Raise exception if thermal limit reached
|
||||
if exit_on_thermal_limit and section == 'CPUTemps':
|
||||
if source_data['Current'] >= CPU_CRITICAL_TEMP:
|
||||
if source_data['Current'] > CPU_TEMPS['Critical']:
|
||||
raise ThermalLimitReachedError('CPU temps reached limit')
|
||||
|
||||
|
||||
|
|
@ -420,7 +514,7 @@ def get_sensor_data_macos() -> dict[Any, Any]:
|
|||
|
||||
def get_temp_str(temp, colored=True) -> str:
|
||||
"""Get colored string based on temp, returns str."""
|
||||
temp_color = None
|
||||
temp_color = ''
|
||||
|
||||
# Safety check
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -42,25 +42,24 @@ def build_self_test_report(test_obj, aborted=False) -> None:
|
|||
last known progress instead of just "was aborted by host."
|
||||
"""
|
||||
report = [ansi.color_string('Self-Test', 'BLUE')]
|
||||
test_details = get_smart_self_test_details(test_obj.dev)
|
||||
test_result = test_details.get('status', {}).get('string', 'Unknown')
|
||||
test_result = get_smart_self_test_last_result(test_obj.dev)
|
||||
|
||||
# Build report
|
||||
if test_obj.disabled or test_obj.status == 'Denied':
|
||||
report.append(ansi.color_string(f' {test_obj.status}', 'RED'))
|
||||
elif test_obj.status == 'N/A' or not test_obj.dev.attributes:
|
||||
report.append(ansi.color_string(f' {test_obj.status}', 'YELLOW'))
|
||||
elif test_obj.status == 'TestInProgress':
|
||||
report.append(ansi.color_string(' Failed to stop previous test', 'RED'))
|
||||
test_obj.set_status('Failed')
|
||||
else:
|
||||
# Other cases include self-test result string
|
||||
report.append(f' {test_result.capitalize()}')
|
||||
if aborted and not (test_obj.passed or test_obj.failed):
|
||||
report.append(ansi.color_string(' Aborted', 'YELLOW'))
|
||||
test_obj.set_status('Aborted')
|
||||
if test_obj.status == 'TestInProgress':
|
||||
report.append(ansi.color_string(' Failed to stop previous test', 'RED'))
|
||||
test_obj.set_status('Failed')
|
||||
elif test_obj.status == 'TimedOut':
|
||||
report.append(ansi.color_string(' TimedOut', 'YELLOW'))
|
||||
elif aborted and not (test_obj.passed or test_obj.failed):
|
||||
report.append(ansi.color_string(' Aborted', 'YELLOW'))
|
||||
test_obj.set_status('Aborted')
|
||||
report.append(f' {test_result}')
|
||||
|
||||
# Done
|
||||
test_obj.report.extend(report)
|
||||
|
|
@ -105,7 +104,7 @@ def enable_smart(dev) -> None:
|
|||
cmd = [
|
||||
'sudo',
|
||||
'smartctl',
|
||||
f'--device={"sat,auto" if dev.use_sat else "auto"}',
|
||||
'--device=auto',
|
||||
'--tolerance=permissive',
|
||||
'--smart=on',
|
||||
dev.path,
|
||||
|
|
@ -201,7 +200,7 @@ def get_attribute_value_string(dev, attr) -> str:
|
|||
return value_str
|
||||
|
||||
|
||||
def get_known_disk_attributes(model) -> None:
|
||||
def get_known_disk_attributes(model) -> dict[str | int, dict[str, Any]]:
|
||||
"""Get known disk attributes based on the device model."""
|
||||
known_attributes = copy.deepcopy(KNOWN_DISK_ATTRIBUTES)
|
||||
|
||||
|
|
@ -219,7 +218,7 @@ def get_known_disk_attributes(model) -> None:
|
|||
return known_attributes
|
||||
|
||||
|
||||
def get_smart_self_test_details(dev) -> dict[Any, Any]:
|
||||
def get_smart_self_test_details(dev) -> dict[str, Any]:
|
||||
"""Shorthand to get deeply nested self-test details, returns dict."""
|
||||
details = {}
|
||||
try:
|
||||
|
|
@ -241,7 +240,9 @@ def get_smart_self_test_last_result(dev) -> str:
|
|||
'ata_smart_self_test_log', {}).get(
|
||||
'standard', {}).get(
|
||||
'table', [])
|
||||
if not data:
|
||||
try:
|
||||
data = data[0]
|
||||
except IndexError:
|
||||
# No results found
|
||||
return result
|
||||
|
||||
|
|
@ -291,7 +292,6 @@ def monitor_smart_self_test(test_obj, header_str, log_path) -> bool:
|
|||
result = get_smart_self_test_last_result(test_obj.dev)
|
||||
if result == 'Unknown':
|
||||
result = 'SMART self-test failed to start'
|
||||
test_obj.dev.add_note(result)
|
||||
test_obj.failed = True
|
||||
test_obj.set_status('TimedOut')
|
||||
break
|
||||
|
|
@ -307,6 +307,11 @@ def monitor_smart_self_test(test_obj, header_str, log_path) -> bool:
|
|||
finished = True
|
||||
break
|
||||
|
||||
# Check if timed out
|
||||
if started and not finished:
|
||||
test_obj.failed = True
|
||||
test_obj.set_status('TimedOut')
|
||||
|
||||
# Done
|
||||
return finished
|
||||
|
||||
|
|
@ -456,7 +461,7 @@ def update_smart_details(dev) -> None:
|
|||
cmd = [
|
||||
'sudo',
|
||||
'smartctl',
|
||||
f'--device={"sat,auto" if dev.use_sat else "auto"}',
|
||||
'--device=auto',
|
||||
'--tolerance=verypermissive',
|
||||
'--all',
|
||||
'--json',
|
||||
|
|
@ -501,6 +506,10 @@ def update_smart_details(dev) -> None:
|
|||
if not updated_attributes:
|
||||
dev.add_note('No NVMe or SMART data available', 'YELLOW')
|
||||
|
||||
# Update iniital_attributes if needed
|
||||
if not dev.initial_attributes:
|
||||
dev.initial_attributes = copy.deepcopy(updated_attributes)
|
||||
|
||||
# Done
|
||||
dev.attributes.update(updated_attributes)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ from dataclasses import dataclass, field
|
|||
from typing import Any
|
||||
|
||||
from wk.cfg.hw import KNOWN_RAM_VENDOR_IDS
|
||||
from wk.cfg.python import DATACLASS_DECORATOR_KWARGS
|
||||
from wk.exe import get_json_from_command, run_program
|
||||
from wk.hw.test import Test
|
||||
from wk.std import PLATFORM, bytes_to_string, string_to_bytes
|
||||
|
|
@ -20,7 +19,7 @@ from wk.ui import ansi
|
|||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass(**DATACLASS_DECORATOR_KWARGS)
|
||||
@dataclass(slots=True)
|
||||
class System:
|
||||
"""Object for tracking system specific hardware data."""
|
||||
cpu_description: str = field(init=False)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@
|
|||
from dataclasses import dataclass, field
|
||||
from typing import Any, Callable
|
||||
|
||||
from wk.cfg.python import DATACLASS_DECORATOR_KWARGS
|
||||
|
||||
@dataclass(**DATACLASS_DECORATOR_KWARGS)
|
||||
@dataclass(slots=True)
|
||||
class Test:
|
||||
"""Object for tracking test specific data."""
|
||||
dev: Any
|
||||
|
|
@ -14,7 +12,6 @@ class Test:
|
|||
name: str
|
||||
disabled: bool = field(init=False, default=False)
|
||||
failed: bool = field(init=False, default=False)
|
||||
hidden: bool = False
|
||||
passed: bool = field(init=False, default=False)
|
||||
report: list[str] = field(init=False, default_factory=list)
|
||||
status: str = field(init=False, default='Pending')
|
||||
|
|
@ -28,7 +25,7 @@ class Test:
|
|||
self.status = status
|
||||
|
||||
|
||||
@dataclass(**DATACLASS_DECORATOR_KWARGS)
|
||||
@dataclass(slots=True)
|
||||
class TestGroup:
|
||||
"""Object for tracking groups of tests."""
|
||||
name: str
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ def case_insensitive_search(
|
|||
path = pathlib.Path(path).resolve()
|
||||
given_path = path.joinpath(item)
|
||||
real_path = None
|
||||
regex = fr'^{item}'
|
||||
regex = fr'^{item}$'
|
||||
|
||||
# Quick check
|
||||
if given_path.exists():
|
||||
|
|
|
|||
|
|
@ -162,6 +162,29 @@ def download_bluescreenview() -> None:
|
|||
delete_from_temp('bluescreenview64.zip')
|
||||
|
||||
|
||||
def download_ddu() -> None:
|
||||
"""Download Display Driver Uninstaller."""
|
||||
archive = download_to_temp('DDU.exe', SOURCES['DDU'])
|
||||
out_path = BIN_DIR.joinpath('DDU')
|
||||
extract_archive(archive, out_path, 'DDU*/*.*', mode='e')
|
||||
out_path = out_path.joinpath('Settings')
|
||||
for item in ('AMD', 'INTEL', 'Languages', 'NVIDIA', 'REALTEK'):
|
||||
extract_archive(
|
||||
archive,
|
||||
out_path.joinpath(item),
|
||||
f'DDU*/Settings/{item}/*',
|
||||
mode='e',
|
||||
)
|
||||
delete_from_temp('DDU.exe')
|
||||
|
||||
|
||||
def download_bcuninstaller() -> None:
|
||||
"""Download Bulk Crap Uninstaller."""
|
||||
archive = download_to_temp('BCU.zip', SOURCES['BCUninstaller'])
|
||||
extract_to_bin(archive, 'BCUninstaller')
|
||||
delete_from_temp('BCU.zip')
|
||||
|
||||
|
||||
def download_erunt() -> None:
|
||||
"""Download ERUNT."""
|
||||
archive = download_to_temp('erunt.zip', SOURCES['ERUNT'])
|
||||
|
|
@ -237,7 +260,11 @@ def download_libreoffice() -> None:
|
|||
"""Download LibreOffice."""
|
||||
for arch in 32, 64:
|
||||
out_path = INSTALLERS_DIR.joinpath(f'LibreOffice{arch}.msi')
|
||||
download_file(out_path, SOURCES[f'LibreOffice{arch}'])
|
||||
download_file(
|
||||
out_path,
|
||||
SOURCES[f'LibreOffice{arch}'],
|
||||
referer='https://www.libreoffice.org/download/download-libreoffice/',
|
||||
)
|
||||
ui.sleep(1)
|
||||
|
||||
|
||||
|
|
@ -345,21 +372,6 @@ def download_snappy_driver_installer_origin() -> None:
|
|||
delete_from_temp('fake.7z')
|
||||
|
||||
|
||||
def download_uninstallview() -> None:
|
||||
"""Download UninstallView."""
|
||||
archive_32 = download_to_temp('uninstallview32.zip', SOURCES['UninstallView32'])
|
||||
archive_64 = download_to_temp('uninstallview64.zip', SOURCES['UninstallView64'])
|
||||
out_path = BIN_DIR.joinpath('UninstallView')
|
||||
extract_archive(archive_64, out_path, 'UninstallView.exe')
|
||||
rename_item(
|
||||
out_path.joinpath('UninstallView.exe'),
|
||||
out_path.joinpath('UninstallView64.exe'),
|
||||
)
|
||||
extract_archive(archive_32, out_path)
|
||||
delete_from_temp('uninstallview32.zip')
|
||||
delete_from_temp('uninstallview64.zip')
|
||||
|
||||
|
||||
def download_wiztree() -> None:
|
||||
"""Download WizTree."""
|
||||
archive = download_to_temp('wiztree.zip', SOURCES['WizTree'])
|
||||
|
|
@ -383,7 +395,7 @@ def download_xmplay() -> None:
|
|||
args = [archive, BIN_DIR.joinpath('XMPlay/plugins')]
|
||||
if archive.name == 'Innocuous.zip':
|
||||
args.append(
|
||||
'Innocuous (v1.5)/Innocuous (Hue Shifted)/'
|
||||
'Innocuous (v1.7)/Innocuous (Hue Shifted)/'
|
||||
'Innocuous (Dark Skies - Purple-80) [L1].xmpskin'
|
||||
)
|
||||
extract_archive(*args, mode='e')
|
||||
|
|
@ -471,6 +483,8 @@ def build_kit() -> None:
|
|||
try_print.run('BleachBit...', download_bleachbit)
|
||||
try_print.run('BlueScreenView...', download_bluescreenview)
|
||||
try_print.run('ERUNT...', download_erunt)
|
||||
try_print.run('BulkCrapUninstaller...', download_bcuninstaller)
|
||||
try_print.run('DDU...', download_ddu)
|
||||
try_print.run('Everything...', download_everything)
|
||||
try_print.run('FastCopy...', download_fastcopy)
|
||||
try_print.run('FurMark...', download_furmark)
|
||||
|
|
@ -482,7 +496,6 @@ def build_kit() -> None:
|
|||
try_print.run('OpenShell...', download_openshell)
|
||||
try_print.run('PuTTY...', download_putty)
|
||||
try_print.run('Snappy Driver Installer...', download_snappy_driver_installer_origin)
|
||||
try_print.run('UninstallView...', download_uninstallview)
|
||||
try_print.run('WizTree...', download_wiztree)
|
||||
try_print.run('XMPlay...', download_xmplay)
|
||||
try_print.run('XMPlay Music...', download_xmplay_music)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
"""WizardKit: UFD Functions"""
|
||||
# vim: sts=2 sw=2 ts=2
|
||||
|
||||
# TODO: Drop OrderedDict use
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import math
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import shutil
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
from collections import OrderedDict
|
||||
from docopt import docopt
|
||||
|
||||
from wk import io, log
|
||||
from wk.cfg.main import KIT_NAME_FULL, KIT_NAME_SHORT
|
||||
from wk.cfg.ufd import (
|
||||
|
|
@ -20,6 +17,7 @@ from wk.cfg.ufd import (
|
|||
BOOT_FILES,
|
||||
IMAGE_BOOT_ENTRIES,
|
||||
ITEMS,
|
||||
ITEMS_FROM_LIVE,
|
||||
ITEMS_HIDDEN,
|
||||
SOURCES,
|
||||
)
|
||||
|
|
@ -30,30 +28,6 @@ from wk.ui import cli as ui
|
|||
|
||||
|
||||
# STATIC VARIABLES
|
||||
DOCSTRING = '''WizardKit: Build UFD
|
||||
|
||||
Usage:
|
||||
build-ufd [options] --ufd-device PATH
|
||||
[--linux PATH]
|
||||
[--main-kit PATH]
|
||||
[--winpe PATH]
|
||||
[--extra-dir PATH]
|
||||
[EXTRA_IMAGES...]
|
||||
build-ufd (-h | --help)
|
||||
|
||||
Options:
|
||||
-e PATH, --extra-dir PATH
|
||||
-k PATH, --main-kit PATH
|
||||
-l PATH, --linux PATH
|
||||
-u PATH, --ufd-device PATH
|
||||
-w PATH, --winpe PATH
|
||||
|
||||
-d --debug Enable debug mode
|
||||
-h --help Show this page
|
||||
-M --use-mbr Use real MBR instead of GPT w/ Protective MBR
|
||||
-F --force Bypass all confirmation messages. USE WITH EXTREME CAUTION!
|
||||
-U --update Don't format device, just update
|
||||
'''
|
||||
LOG = logging.getLogger(__name__)
|
||||
EXTRA_IMAGES_LIST = '/mnt/UFD/arch/extra_images.list'
|
||||
MIB = 1024 ** 2
|
||||
|
|
@ -62,6 +36,54 @@ UFD_LABEL = f'{KIT_NAME_SHORT}_UFD'
|
|||
|
||||
|
||||
# Functions
|
||||
def argparse_helper() -> dict[str, None|bool|str]:
|
||||
"""Helper function to setup and return args, returns dict.
|
||||
|
||||
NOTE: A dict is used to match the legacy code.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='build-ufd',
|
||||
description=f'{KIT_NAME_FULL}: Build UFD',
|
||||
)
|
||||
parser.add_argument('-u', '--ufd-device', required=True)
|
||||
parser.add_argument('-l', '--linux', required=False)
|
||||
parser.add_argument('-e', '--extra-dir', required=False)
|
||||
parser.add_argument('-k', '--main-kit', required=False)
|
||||
parser.add_argument('-w', '--winpe', required=False)
|
||||
parser.add_argument(
|
||||
'-d', '--debug', action='store_true',
|
||||
help='Enable debug mode',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-M', '--use-mbr', action='store_true',
|
||||
help='Use real MBR instead of GPT w/ Protective MBR',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-F', '--force', action='store_true',
|
||||
help='Bypass all confirmation messages. USE WITH EXTREME CAUTION!',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-U', '--update', action='store_true',
|
||||
help="Don't format device, just update",
|
||||
)
|
||||
parser.add_argument(
|
||||
'EXTRA_IMAGES', nargs='*',
|
||||
)
|
||||
args = parser.parse_args()
|
||||
legacy_args = {
|
||||
'--debug': args.debug,
|
||||
'--extra-dir': args.extra_dir,
|
||||
'--force': args.force,
|
||||
'--linux': args.linux,
|
||||
'--main-kit': args.main_kit,
|
||||
'--ufd-device': args.ufd_device,
|
||||
'--update': args.update,
|
||||
'--use-mbr': args.use_mbr,
|
||||
'--winpe': args.winpe,
|
||||
'EXTRA_IMAGES': args.EXTRA_IMAGES,
|
||||
}
|
||||
return legacy_args
|
||||
|
||||
def apply_image(part_path, image_path, hide_macos_boot=True) -> None:
|
||||
"""Apply raw image to dev_path using dd."""
|
||||
cmd = [
|
||||
|
|
@ -94,7 +116,12 @@ def apply_image(part_path, image_path, hide_macos_boot=True) -> None:
|
|||
|
||||
def build_ufd() -> None:
|
||||
"""Build UFD using selected sources."""
|
||||
args = docopt(DOCSTRING)
|
||||
try:
|
||||
args = argparse_helper()
|
||||
except SystemExit:
|
||||
print('')
|
||||
ui.pause('Press Enter to exit...')
|
||||
raise
|
||||
if args['--debug']:
|
||||
log.enable_debug_mode()
|
||||
if args['--update'] and args['EXTRA_IMAGES']:
|
||||
|
|
@ -125,7 +152,7 @@ def build_ufd() -> None:
|
|||
if not args['--update']:
|
||||
ui.print_info('Prep UFD')
|
||||
try_print.run(
|
||||
message='Zeroing first 64MiB...',
|
||||
message='Zeroing first 1MiB...',
|
||||
function=zero_device,
|
||||
dev_path=ufd_dev,
|
||||
)
|
||||
|
|
@ -148,6 +175,13 @@ def build_ufd() -> None:
|
|||
dev_path=ufd_dev,
|
||||
label=UFD_LABEL,
|
||||
)
|
||||
try_print.run(
|
||||
message='Hiding extra partition(s)...',
|
||||
function=hide_extra_partitions,
|
||||
dev_path=ufd_dev,
|
||||
num_parts=len(extra_images),
|
||||
use_mbr=args['--use-mbr'],
|
||||
)
|
||||
ufd_dev_first_partition = find_first_partition(ufd_dev)
|
||||
|
||||
# Mount UFD
|
||||
|
|
@ -173,14 +207,25 @@ def build_ufd() -> None:
|
|||
message='Removing Linux...',
|
||||
function=remove_arch,
|
||||
)
|
||||
# Copy boot files
|
||||
ui.print_standard(' ')
|
||||
ui.print_info('Boot Files')
|
||||
for s_section, s_items in ITEMS_FROM_LIVE.items():
|
||||
s_section = pathlib.Path(s_section)
|
||||
try_print.run(
|
||||
message=f'Copying {s_section}...',
|
||||
function=copy_source,
|
||||
source=s_section,
|
||||
items=s_items,
|
||||
from_live=True,
|
||||
overwrite=True,
|
||||
)
|
||||
os.rename('/mnt/UFD/EFI/Boot/refind_x64.efi', '/mnt/UFD/EFI/Boot/bootx64.efi')
|
||||
|
||||
|
||||
# Copy sources
|
||||
ui.print_standard(' ')
|
||||
ui.print_info('Copy Sources')
|
||||
try_print.run(
|
||||
'Copying Memtest86...', io.recursive_copy,
|
||||
'/usr/share/memtest86-efi/', '/mnt/UFD/EFI/Memtest86/', overwrite=True,
|
||||
)
|
||||
for s_label, s_path in sources.items():
|
||||
try_print.run(
|
||||
message=f'Copying {s_label}...',
|
||||
|
|
@ -276,9 +321,9 @@ def confirm_selections(update=False) -> None:
|
|||
ui.print_standard(' ')
|
||||
|
||||
|
||||
def copy_source(source, items, overwrite=False) -> None:
|
||||
def copy_source(source, items, from_live=False, overwrite=False) -> None:
|
||||
"""Copy source items to /mnt/UFD."""
|
||||
is_image = source.is_file()
|
||||
is_image = not from_live and (source.is_file() or source.is_block_device())
|
||||
items_not_found = False
|
||||
|
||||
# Mount source if necessary
|
||||
|
|
@ -287,7 +332,14 @@ def copy_source(source, items, overwrite=False) -> None:
|
|||
|
||||
# Copy items
|
||||
for i_source, i_dest in items:
|
||||
i_source = f'{"/mnt/Source" if is_image else source}{i_source}'
|
||||
if from_live:
|
||||
# Don't prepend source
|
||||
pass
|
||||
elif is_image:
|
||||
i_source = f'/mnt/Source{i_source}'
|
||||
else:
|
||||
# Prepend source
|
||||
i_source = f'{source}{i_source}'
|
||||
i_dest = f'/mnt/UFD{i_dest}'
|
||||
try:
|
||||
io.recursive_copy(i_source, i_dest, overwrite=overwrite)
|
||||
|
|
@ -333,7 +385,7 @@ def create_table(dev_path, use_mbr=False, images=None) -> None:
|
|||
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',
|
||||
f'mkpart primary "fat32" {start}B {end-1}B',
|
||||
)
|
||||
start += part
|
||||
|
||||
|
|
@ -419,6 +471,17 @@ def hide_items(ufd_dev_first_partition, items) -> None:
|
|||
run_program(cmd, shell=True, check=False)
|
||||
|
||||
|
||||
def hide_extra_partitions(dev_path, num_parts, use_mbr) -> None:
|
||||
if use_mbr:
|
||||
# Bail early
|
||||
return
|
||||
|
||||
for part_id in range(num_parts):
|
||||
part_id += 2 # Extra partitions start at 2
|
||||
cmd = ['sfdisk', '--part-attrs', dev_path, str(part_id), 'RequiredPartition,62,63']
|
||||
run_program(cmd, check=False)
|
||||
|
||||
|
||||
def install_syslinux_to_dev(ufd_dev, use_mbr) -> None:
|
||||
"""Install Syslinux to UFD (dev)."""
|
||||
cmd = [
|
||||
|
|
@ -456,6 +519,7 @@ def is_valid_path(path_obj, path_type) -> bool:
|
|||
valid_path = path_obj.is_file() and path_obj.suffix.lower() == '.img'
|
||||
elif path_type == 'ISO':
|
||||
valid_path = path_obj.is_file() and path_obj.suffix.lower() == '.iso'
|
||||
valid_path = valid_path or re.match(r'^/dev/sr\d+$', str(path_obj))
|
||||
elif path_type == 'UFD':
|
||||
valid_path = path_obj.is_block_device()
|
||||
|
||||
|
|
@ -551,7 +615,7 @@ def update_boot_entries(ufd_dev, images=None) -> None:
|
|||
'sed',
|
||||
'--in-place',
|
||||
'--regexp-extended',
|
||||
f's#archisolabel={ISO_LABEL}#archisodevice=/dev/disk/by-uuid/{uuids[0]}#',
|
||||
f's/___+/{uuids[0]}/',
|
||||
*configs,
|
||||
]
|
||||
run_program(cmd)
|
||||
|
|
@ -618,7 +682,7 @@ def update_boot_entries(ufd_dev, images=None) -> None:
|
|||
|
||||
def verify_sources(args, ufd_sources) -> dict[str, pathlib.Path]:
|
||||
"""Check all sources and abort if necessary, returns dict."""
|
||||
sources = OrderedDict()
|
||||
sources = {}
|
||||
|
||||
for label, data in ufd_sources.items():
|
||||
s_path = args[data['Arg']]
|
||||
|
|
@ -628,10 +692,11 @@ def verify_sources(args, ufd_sources) -> dict[str, pathlib.Path]:
|
|||
except FileNotFoundError:
|
||||
ui.print_error(f'ERROR: {label} not found: {s_path}')
|
||||
ui.abort()
|
||||
if not is_valid_path(s_path_obj, data['Type']):
|
||||
ui.print_error(f'ERROR: Invalid {label} source: {s_path}')
|
||||
ui.abort()
|
||||
sources[label] = s_path_obj
|
||||
else:
|
||||
if not is_valid_path(s_path_obj, data['Type']):
|
||||
ui.print_error(f'ERROR: Invalid {label} source: {s_path}')
|
||||
ui.abort()
|
||||
sources[label] = s_path_obj
|
||||
|
||||
return sources
|
||||
|
||||
|
|
@ -654,12 +719,12 @@ def verify_ufd(dev_path) -> pathlib.Path:
|
|||
|
||||
|
||||
def zero_device(dev_path) -> None:
|
||||
"""Zero-out first 64MB of device."""
|
||||
"""Zero-out first 1MB of device."""
|
||||
cmd = [
|
||||
'sudo',
|
||||
'dd',
|
||||
'bs=4M',
|
||||
'count=16',
|
||||
'bs=1M',
|
||||
'count=1',
|
||||
'if=/dev/zero',
|
||||
f'of={dev_path}',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -39,16 +39,21 @@ def enable_debug_mode() -> None:
|
|||
|
||||
|
||||
def format_log_path(
|
||||
log_dir: None | pathlib.Path | str = None,
|
||||
log_name: None | str = None,
|
||||
log_dir: pathlib.Path | str | None = None,
|
||||
log_name: str | None = None,
|
||||
append: bool = False,
|
||||
kit: bool = False,
|
||||
sub_dir: str | None = None,
|
||||
timestamp: bool = False,
|
||||
kit: bool = False, tool: bool = False, append: bool = False,
|
||||
tool: bool = False,
|
||||
) -> pathlib.Path:
|
||||
"""Format path based on args passed, returns pathlib.Path obj."""
|
||||
log_path = pathlib.Path(
|
||||
f'{log_dir if log_dir else DEFAULT_LOG_DIR}/'
|
||||
f'{cfg.main.KIT_NAME_FULL+"/" if kit else ""}'
|
||||
f'{"Tools/" if tool else ""}'
|
||||
f'{sub_dir+"_" if sub_dir else ""}'
|
||||
f'{time.strftime("%Y-%m-%d_%H%M%S%z") if sub_dir else ""}/'
|
||||
f'{log_name if log_name else DEFAULT_LOG_NAME}'
|
||||
f'{"_" if timestamp else ""}'
|
||||
f'{time.strftime("%Y-%m-%d_%H%M%S%z") if timestamp else ""}'
|
||||
|
|
@ -127,9 +132,11 @@ def start(config: dict[str, str] | None = None) -> None:
|
|||
|
||||
|
||||
def update_log_path(
|
||||
dest_dir: None | pathlib.Path | str = None,
|
||||
dest_name: None | str = None,
|
||||
keep_history: bool = True, timestamp: bool = True, append: bool = False,
|
||||
dest_dir: None | pathlib.Path | str = None,
|
||||
dest_name: None | str = None,
|
||||
append: bool = False,
|
||||
keep_history: bool = True,
|
||||
timestamp: bool = True,
|
||||
) -> None:
|
||||
"""Moves current log file to new path and updates the root logger."""
|
||||
root_logger = logging.getLogger()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import logging
|
|||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import re
|
||||
|
||||
from contextlib import suppress
|
||||
from typing import Any
|
||||
|
|
@ -26,7 +25,7 @@ from wk.cfg.windows_builds import (
|
|||
OUTDATED_BUILD_NUMBERS,
|
||||
WINDOWS_BUILDS,
|
||||
)
|
||||
from wk.exe import get_json_from_command, run_program
|
||||
from wk.exe import get_json_from_command, run_program, wait_for_procs
|
||||
from wk.kit.tools import find_kit_dir
|
||||
from wk.std import (
|
||||
GenericError,
|
||||
|
|
@ -74,9 +73,6 @@ KNOWN_HIVE_NAMES = {
|
|||
RAM_OK = 5.5 * 1024**3 # ~6 GiB assuming a bit of shared memory
|
||||
RAM_WARNING = 3.5 * 1024**3 # ~4 GiB assuming a bit of shared memory
|
||||
REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer'
|
||||
REGEX_4K_ALIGNMENT = re.compile(
|
||||
r'^(?P<description>.*?)\s+(?P<size>\d+)\s+(?P<offset>\d+)',
|
||||
)
|
||||
SLMGR = pathlib.Path(f'{os.environ.get("SYSTEMROOT")}/System32/slmgr.vbs')
|
||||
SYSTEMDRIVE = os.environ.get('SYSTEMDRIVE')
|
||||
|
||||
|
|
@ -169,29 +165,23 @@ def set_timezone(zone) -> None:
|
|||
# Info Functions
|
||||
def check_4k_alignment(show_alert=False) -> list[str]:
|
||||
"""Check if all partitions are 4K aligned, returns list."""
|
||||
cmd = ['WMIC', 'partition', 'get', 'Caption,Size,StartingOffset']
|
||||
script_path = find_kit_dir('Scripts').joinpath('check_partition_alignment.ps1')
|
||||
cmd = ['PowerShell', '-ExecutionPolicy', 'Bypass', '-File', script_path]
|
||||
json_data = get_json_from_command(cmd)
|
||||
report = []
|
||||
show_alert = False
|
||||
|
||||
# Check offsets
|
||||
proc = run_program(cmd)
|
||||
for line in proc.stdout.splitlines():
|
||||
line = line.strip()
|
||||
if not line or not line.startswith('Disk'):
|
||||
continue
|
||||
match = REGEX_4K_ALIGNMENT.match(line)
|
||||
if not match:
|
||||
LOG.error('Failed to parse partition info for: %s', line)
|
||||
continue
|
||||
if int(match.group('offset')) % 4096 != 0:
|
||||
report.append(
|
||||
ansi.color_string(
|
||||
f'{match.group("description")}'
|
||||
f' ({bytes_to_string(match.group("size"), decimals=1)})'
|
||||
,
|
||||
'RED'
|
||||
)
|
||||
)
|
||||
for part in json_data:
|
||||
if part['StartingOffset'] % 4096 != 0:
|
||||
report.append(
|
||||
ansi.color_string(
|
||||
f'{part["Name"]}'
|
||||
f' ({bytes_to_string(part["Size"], decimals=1)})'
|
||||
,
|
||||
'RED'
|
||||
)
|
||||
)
|
||||
|
||||
# Show alert
|
||||
if show_alert:
|
||||
|
|
@ -203,6 +193,7 @@ def check_4k_alignment(show_alert=False) -> list[str]:
|
|||
0,
|
||||
ansi.color_string('One or more partitions not 4K aligned', 'YELLOW'),
|
||||
)
|
||||
report.sort()
|
||||
return report
|
||||
|
||||
|
||||
|
|
@ -224,45 +215,52 @@ def export_bitlocker_info() -> None:
|
|||
_f.write(f'{proc.stdout}\n\n')
|
||||
|
||||
|
||||
def get_installed_antivirus() -> list[str]:
|
||||
"""Get list of installed antivirus programs, returns list."""
|
||||
cmd = [
|
||||
'WMIC', r'/namespace:\\root\SecurityCenter2',
|
||||
'path', 'AntivirusProduct',
|
||||
'get', 'displayName', '/value',
|
||||
]
|
||||
products = []
|
||||
report = []
|
||||
def get_installed_antivirus() -> dict[str, dict]:
|
||||
"""Get installed antivirus products and their status, returns dict."""
|
||||
script_path = find_kit_dir('Scripts').joinpath('check_av.ps1')
|
||||
cmd = ['PowerShell', '-ExecutionPolicy', 'Bypass', '-File', script_path]
|
||||
json_data = get_json_from_command(cmd)
|
||||
products = {}
|
||||
|
||||
# Get list of products
|
||||
proc = run_program(cmd)
|
||||
for line in proc.stdout.splitlines():
|
||||
line = line.strip()
|
||||
if '=' in line:
|
||||
products.append(line.split('=')[1])
|
||||
# Check state and build dict
|
||||
for p in json_data:
|
||||
name = p['displayName']
|
||||
state = p['productState']
|
||||
enabled = ((state>>8) & 0x11) in (0x10, 0x11) # middle two hex digits
|
||||
outdated = (state & 0x11) != 0x00 # last two hex digits
|
||||
products[name] = {
|
||||
'Enabled': enabled,
|
||||
'Outdated': outdated,
|
||||
'State': state,
|
||||
}
|
||||
return products
|
||||
|
||||
|
||||
def list_installed_antivirus() -> list[str]:
|
||||
"""Get list of installed antivirus programs, returns list."""
|
||||
products = get_installed_antivirus()
|
||||
products_active = []
|
||||
products_inactive = []
|
||||
|
||||
# Check product(s) status
|
||||
for product in sorted(products):
|
||||
cmd = [
|
||||
'WMIC', r'/namespace:\\root\SecurityCenter2',
|
||||
'path', 'AntivirusProduct',
|
||||
'where', f'displayName="{product}"',
|
||||
'get', 'productState', '/value',
|
||||
]
|
||||
proc = run_program(cmd)
|
||||
state = proc.stdout.split('=')[1]
|
||||
state = hex(int(state))
|
||||
if str(state)[3:5] not in ['10', '11']:
|
||||
report.append(ansi.color_string(f'[Disabled] {product}', 'YELLOW'))
|
||||
for name, details in products.items():
|
||||
if details['Enabled']:
|
||||
if details['Outdated']:
|
||||
products_active.append(ansi.color_string(f'{name} [OUTDATED]', 'YELLOW'))
|
||||
else:
|
||||
products_active.append(name)
|
||||
else:
|
||||
report.append(product)
|
||||
# Disabled
|
||||
products_inactive.append(ansi.color_string(f'[Disabled] {name}', 'YELLOW'))
|
||||
|
||||
# Final check
|
||||
if not report:
|
||||
report.append(ansi.color_string('No products detected', 'RED'))
|
||||
if not (products_active or products_inactive):
|
||||
products_inactive.append(ansi.color_string('No products detected', 'RED'))
|
||||
|
||||
# Done
|
||||
return report
|
||||
products_active.sort()
|
||||
products_inactive.sort()
|
||||
return products_active + products_inactive
|
||||
|
||||
|
||||
def get_installed_ram(as_list=False, raise_exceptions=False) -> list | str:
|
||||
|
|
@ -744,5 +742,62 @@ def stop_service(service_name) -> None:
|
|||
raise GenericError(f'Failed to stop service {service_name}')
|
||||
|
||||
|
||||
# Winget Functions
|
||||
def winget_check(raise_exceptions: bool = False) -> None:
|
||||
"""Check if winget is present, install if not."""
|
||||
cmd = [
|
||||
'powershell',
|
||||
'-ExecutionPolicy', 'bypass',
|
||||
'-File', find_kit_dir('Scripts').joinpath('install_winget.ps1'),
|
||||
]
|
||||
proc = run_program(cmd, check=False)
|
||||
|
||||
# Raise exception if requested
|
||||
if raise_exceptions:
|
||||
if proc.returncode == 1:
|
||||
raise GenericWarning('Already installed')
|
||||
if proc.returncode == 2:
|
||||
raise GenericError('Failed to install')
|
||||
|
||||
|
||||
def winget_import(group_name: str = 'default') -> None:
|
||||
"""Use winget to import a set of applications.
|
||||
|
||||
group_name should be the name of a JSON file exported from winget.
|
||||
|
||||
NOTE: The path is relative to .bin/Scripts/wk/cfg/winget/
|
||||
"""
|
||||
cmd = [
|
||||
'winget',
|
||||
'import', '--import-file',
|
||||
str(find_kit_dir('Scripts').joinpath(f'wk/cfg/winget/{group_name}.json')),
|
||||
]
|
||||
tmp_file = fr'{os.environ.get("TMP")}\run_winget.cmd'
|
||||
if CONEMU:
|
||||
with open(tmp_file, 'w', encoding='utf-8') as _f:
|
||||
_f.write('@echo off\n')
|
||||
_f.write(" ".join(cmd))
|
||||
cmd = ('cmd', '/c', tmp_file, '-new_console:n', '-new_console:s33V')
|
||||
run_program(cmd, check=False, pipe=False)
|
||||
sleep(1)
|
||||
wait_for_procs('winget.exe')
|
||||
|
||||
|
||||
def winget_upgrade() -> None:
|
||||
"""Upgrade all supported programs with winget, returns subprocess.Popen."""
|
||||
cmd = ['winget', 'upgrade', '--all']
|
||||
|
||||
# Adjust if running inside ConEmu
|
||||
tmp_file = fr'{os.environ.get("TMP")}\run_winget.cmd'
|
||||
if CONEMU:
|
||||
with open(tmp_file, 'w', encoding='utf-8') as _f:
|
||||
_f.write('@echo off\n')
|
||||
_f.write(" ".join(cmd))
|
||||
cmd = ('cmd', '/c', tmp_file, '-new_console:n', '-new_console:s33V')
|
||||
run_program(cmd, check=False, pipe=False)
|
||||
sleep(1)
|
||||
wait_for_procs('winget.exe')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("This file is not meant to be called directly.")
|
||||
|
|
|
|||
|
|
@ -298,6 +298,7 @@ def init_run(options) -> None:
|
|||
|
||||
def init_session(options) -> None:
|
||||
"""Initialize Auto Repairs session."""
|
||||
_ = options # Suppress linting error and reserve for furture use
|
||||
reg_set_value('HKCU', AUTO_REPAIR_KEY, 'SessionStarted', 1, 'DWORD')
|
||||
reg_set_value('HKCU', AUTO_REPAIR_KEY, 'LogName', get_root_logger_path().stem, 'SZ')
|
||||
|
||||
|
|
@ -311,12 +312,11 @@ def init_session(options) -> None:
|
|||
set_timezone(WINDOWS_TIME_ZONE)
|
||||
|
||||
# One-time tasks
|
||||
TRY_PRINT.run(
|
||||
'Run AVRemover...', run_tool, 'AVRemover', 'AVRemover',
|
||||
download=True, msg_good='DONE',
|
||||
)
|
||||
if options['Run TDSSKiller (once)']['Selected']:
|
||||
TRY_PRINT.run('Running TDSSKiller...', run_tdsskiller, msg_good='DONE')
|
||||
if options['Run AVRemover (once)']['Selected']:
|
||||
TRY_PRINT.run(
|
||||
'Run AVRemover...', run_tool, 'AVRemover', 'AVRemover',
|
||||
download=True, msg_good='DONE',
|
||||
)
|
||||
print('')
|
||||
reboot(30)
|
||||
|
||||
|
|
@ -649,6 +649,14 @@ def auto_bleachbit(group, name) -> None:
|
|||
save_settings(group, name, result=result)
|
||||
|
||||
|
||||
def auto_bcuninstaller(group, name) -> None:
|
||||
"""Run BCUninstaller."""
|
||||
result = TRY_PRINT.run(
|
||||
'BCUninstaller...', run_bcuninstaller, msg_good='DONE',
|
||||
)
|
||||
save_settings(group, name, result=result)
|
||||
|
||||
|
||||
def auto_chkdsk(group, name) -> None:
|
||||
"""Run CHKDSK repairs."""
|
||||
needs_reboot = False
|
||||
|
|
@ -825,14 +833,6 @@ def auto_system_restore_set_size(group, name) -> None:
|
|||
save_settings(group, name, result=result)
|
||||
|
||||
|
||||
def auto_uninstallview(group, name) -> None:
|
||||
"""Run UninstallView."""
|
||||
result = TRY_PRINT.run(
|
||||
'UninstallView...', run_uninstallview, msg_good='DONE',
|
||||
)
|
||||
save_settings(group, name, result=result)
|
||||
|
||||
|
||||
def auto_windows_updates_disable(group, name) -> None:
|
||||
"""Disable Windows Updates."""
|
||||
result = TRY_PRINT.run('Disable Windows Updates...', disable_windows_updates)
|
||||
|
|
@ -1058,6 +1058,11 @@ def run_bleachbit(cleaners, preview=True) -> None:
|
|||
)
|
||||
|
||||
|
||||
def run_bcuninstaller() -> None:
|
||||
"""Run BCUninstaller."""
|
||||
run_tool('BCUninstaller', 'BCUninstaller')
|
||||
|
||||
|
||||
def run_hitmanpro() -> None:
|
||||
"""Run HitmanPro scan."""
|
||||
log_path = format_log_path(log_name='HitmanPro', timestamp=True, tool=True)
|
||||
|
|
@ -1167,29 +1172,6 @@ def run_rkill() -> None:
|
|||
run_tool('RKill', 'RKill', *cmd_args, download=True)
|
||||
|
||||
|
||||
def run_tdsskiller() -> None:
|
||||
"""Run TDSSKiller scan."""
|
||||
log_path = format_log_path(log_name='TDSSKiller', timestamp=True, tool=True)
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
quarantine_path = set_quarantine_path('TDSSKiller')
|
||||
quarantine_path.mkdir(parents=True, exist_ok=True)
|
||||
cmd_args = (
|
||||
'-accepteula',
|
||||
'-accepteulaksn',
|
||||
'-l', log_path,
|
||||
'-qpath', quarantine_path,
|
||||
'-qsus',
|
||||
'-dcexact',
|
||||
'-silent',
|
||||
)
|
||||
run_tool('TDSSKiller', 'TDSSKiller', *cmd_args, download=True)
|
||||
|
||||
|
||||
def run_uninstallview() -> None:
|
||||
"""Run UninstallView."""
|
||||
run_tool('UninstallView', 'UninstallView')
|
||||
|
||||
|
||||
# OS Built-in Functions
|
||||
def create_custom_power_plan(enable_sleep=True, keep_display_on=False) -> None:
|
||||
"""Create new power plan and set as active."""
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ from wk.cfg.setup import (
|
|||
REG_WINDOWS_EXPLORER,
|
||||
REG_OPEN_SHELL_SETTINGS,
|
||||
REG_OPEN_SHELL_LOW_POWER_IDLE,
|
||||
REG_WINDOWS_BSOD_MINIDUMPS,
|
||||
UBLOCK_ORIGIN_URLS,
|
||||
)
|
||||
from wk.exe import kill_procs, run_program, popen_program
|
||||
from wk.io import case_insensitive_path, get_path_obj
|
||||
from wk.kit.tools import (
|
||||
ARCH,
|
||||
download_tool,
|
||||
extract_archive,
|
||||
extract_tool,
|
||||
find_kit_dir,
|
||||
|
|
@ -37,16 +37,21 @@ from wk.os.win import (
|
|||
OS_VERSION,
|
||||
activate_with_bios,
|
||||
check_4k_alignment,
|
||||
get_installed_antivirus,
|
||||
get_installed_ram,
|
||||
get_os_activation,
|
||||
get_os_name,
|
||||
get_raw_disks,
|
||||
get_service_status,
|
||||
get_volume_usage,
|
||||
is_activated,
|
||||
is_secure_boot_enabled,
|
||||
list_installed_antivirus,
|
||||
reg_set_value,
|
||||
reg_write_settings,
|
||||
stop_service,
|
||||
winget_check,
|
||||
winget_import,
|
||||
winget_upgrade,
|
||||
)
|
||||
from wk.repairs.win import (
|
||||
WIDTH,
|
||||
|
|
@ -408,7 +413,7 @@ def auto_config_browsers() -> None:
|
|||
'Set default browser...', set_default_browser, msg_good='STARTED',
|
||||
)
|
||||
print(prompt, end='', flush=True)
|
||||
ui.pause('')
|
||||
ui.pause(' ')
|
||||
|
||||
# Move cursor to beginning of the previous line and clear prompt
|
||||
print(f'\033[F\r{" "*len(prompt)}\r', end='', flush=True)
|
||||
|
|
@ -424,6 +429,11 @@ def auto_config_open_shell() -> None:
|
|||
TRY_PRINT.run('Open Shell...', config_open_shell)
|
||||
|
||||
|
||||
def auto_disable_password_expiration() -> None:
|
||||
"""Disable password expiration for all users."""
|
||||
TRY_PRINT.run('Disable password expiration...', disable_password_expiration)
|
||||
|
||||
|
||||
def auto_export_aida64_report() -> None:
|
||||
"""Export AIDA64 reports."""
|
||||
TRY_PRINT.run('AIDA64 Report...', export_aida64_report)
|
||||
|
|
@ -450,12 +460,22 @@ def auto_install_open_shell() -> None:
|
|||
|
||||
def auto_install_software_bundle() -> None:
|
||||
"""Install standard software bundle."""
|
||||
TRY_PRINT.run('Software Bundle...', install_software_bundle)
|
||||
TRY_PRINT.run('Software Bundle...', winget_import, group_name='default')
|
||||
|
||||
|
||||
def auto_install_software_upgrades() -> None:
|
||||
"""Upgrade all supported installed software."""
|
||||
TRY_PRINT.run('Software Upgrades...', winget_upgrade)
|
||||
|
||||
|
||||
def auto_install_vcredists() -> None:
|
||||
"""Install latest supported Visual C++ runtimes."""
|
||||
TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists)
|
||||
TRY_PRINT.run('Visual C++ Runtimes...', winget_import, group_name='vcredists')
|
||||
|
||||
|
||||
def auto_install_winget() -> None:
|
||||
"""Install winget if needed."""
|
||||
TRY_PRINT.run('Winget...', winget_check, raise_exceptions=True)
|
||||
|
||||
|
||||
def auto_open_device_manager() -> None:
|
||||
|
|
@ -468,6 +488,11 @@ def auto_open_hwinfo_sensors() -> None:
|
|||
TRY_PRINT.run('HWiNFO Sensors...', open_hwinfo_sensors)
|
||||
|
||||
|
||||
def auto_open_microsoft_store_updates() -> None:
|
||||
"""Opem Microsoft Store Updates."""
|
||||
TRY_PRINT.run('Microsoft Store Updates...', open_microsoft_store_updates)
|
||||
|
||||
|
||||
def auto_open_snappy_driver_installer_origin() -> None:
|
||||
"""Open Snappy Driver Installer Origin."""
|
||||
TRY_PRINT.run('Snappy Driver Installer...', open_snappy_driver_installer_origin)
|
||||
|
|
@ -496,7 +521,7 @@ def auto_show_4k_alignment_check() -> None:
|
|||
|
||||
def auto_show_installed_antivirus() -> None:
|
||||
"""Display installed antivirus."""
|
||||
TRY_PRINT.run('Virus Protection...', get_installed_antivirus)
|
||||
TRY_PRINT.run('Virus Protection...', list_installed_antivirus)
|
||||
|
||||
|
||||
def auto_show_installed_ram() -> None:
|
||||
|
|
@ -603,10 +628,16 @@ def disable_chrome_notifications() -> None:
|
|||
pref_file.write_text(json.dumps(pref_data, separators=(',', ':')))
|
||||
|
||||
|
||||
def disable_password_expiration() -> None:
|
||||
"""Disable password expiration for all users."""
|
||||
script_path = find_kit_dir('Scripts').joinpath('disable_password_expiration.ps1')
|
||||
cmd = ['PowerShell', '-ExecutionPolicy', 'Bypass', '-File', script_path]
|
||||
run_program(cmd)
|
||||
|
||||
|
||||
def enable_bsod_minidumps() -> None:
|
||||
"""Enable saving minidumps during BSoDs."""
|
||||
cmd = ['wmic', 'RECOVEROS', 'set', 'DebugInfoType', '=', '3']
|
||||
run_program(cmd)
|
||||
reg_write_settings(REG_WINDOWS_BSOD_MINIDUMPS)
|
||||
|
||||
|
||||
def enable_ublock_origin() -> None:
|
||||
|
|
@ -761,7 +792,7 @@ def install_open_shell() -> None:
|
|||
skin_zip = get_tool_path('OpenShell', 'Fluent-Metro', suffix='zip')
|
||||
|
||||
# Bail early
|
||||
if OS_VERSION != 10:
|
||||
if OS_VERSION < 10:
|
||||
raise GenericWarning('Unsupported OS')
|
||||
|
||||
# Install OpenShell
|
||||
|
|
@ -786,48 +817,6 @@ def install_open_shell() -> None:
|
|||
run_program(cmd)
|
||||
|
||||
|
||||
def install_software_bundle() -> None:
|
||||
"""Install standard software bundle."""
|
||||
download_tool('Ninite', 'Software Bundle')
|
||||
installer = get_tool_path('Ninite', 'Software Bundle')
|
||||
msg = 'Waiting for installations to finish...'
|
||||
warning = 'NOTE: Press CTRL+c to manually resume if it gets stuck...'
|
||||
|
||||
# Start installations and wait for them to finish
|
||||
ui.print_standard(msg)
|
||||
ui.print_warning(warning, end='', flush=True)
|
||||
proc = popen_program([installer])
|
||||
try:
|
||||
proc.wait()
|
||||
except KeyboardInterrupt:
|
||||
# Assuming user-forced continue
|
||||
pass
|
||||
|
||||
# Clear info lines
|
||||
print(
|
||||
'\r\033[0K' # Cursor to start of current line and clear to end of line
|
||||
'\033[F\033[54C' # Cursor to start of prev line and then move 54 right
|
||||
'\033[0K', # Clear from cursor to end of line
|
||||
end='', flush=True)
|
||||
|
||||
|
||||
def install_vcredists() -> None:
|
||||
"""Install latest supported Visual C++ runtimes."""
|
||||
for year in (2012, 2013, 2022):
|
||||
cmd_args = ['/install', '/passive', '/norestart']
|
||||
if year == 2012:
|
||||
cmd_args.pop(0)
|
||||
name = f'VCRedist_{year}_x32'
|
||||
download_tool('VCRedist', name)
|
||||
installer = get_tool_path('VCRedist', name)
|
||||
run_program([installer, *cmd_args])
|
||||
if ARCH == '64':
|
||||
name = f'{name[:-2]}64'
|
||||
download_tool('VCRedist', name)
|
||||
installer = get_tool_path('VCRedist', name)
|
||||
run_program([installer, *cmd_args])
|
||||
|
||||
|
||||
def uninstall_firefox() -> None:
|
||||
"""Uninstall all copies of Firefox."""
|
||||
json_file = format_log_path(log_name='Installed Programs', timestamp=True)
|
||||
|
|
@ -952,8 +941,19 @@ def open_hwinfo_sensors() -> None:
|
|||
run_tool('HWiNFO', 'HWiNFO', popen=True)
|
||||
|
||||
|
||||
def open_microsoft_store_updates() -> None:
|
||||
"""Open Microsoft Store to the updates page."""
|
||||
popen_program(['explorer', 'ms-windows-store:updates'])
|
||||
|
||||
|
||||
def open_snappy_driver_installer_origin() -> None:
|
||||
"""Open Snappy Driver Installer Origin."""
|
||||
if OS_VERSION == 11:
|
||||
appid_services = ['appid', 'appidsvc', 'applockerfltr']
|
||||
for svc in appid_services:
|
||||
stop_service(svc)
|
||||
if any([get_service_status(s) != 'stopped' for s in appid_services]):
|
||||
raise GenericWarning('Failed to stop AppID services')
|
||||
run_tool('SDIO', 'SDIO', cwd=True, pipe=True, popen=True)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ class Menu():
|
|||
# Display item in YELLOW
|
||||
disabled = True
|
||||
checkmark = '*'
|
||||
if 'DISPLAY' in os.environ or PLATFORM == 'Darwin':
|
||||
if 'CONEMUPID' in os.environ or 'DISPLAY' in os.environ or PLATFORM == 'Darwin':
|
||||
checkmark = '✓'
|
||||
display_name = f'{index if index else name[:1].upper()}: '
|
||||
if not (index and index >= 10):
|
||||
|
|
@ -678,10 +678,10 @@ def ask(prompt_msg: str) -> bool:
|
|||
# Show prompt
|
||||
response = input_text(f'{prompt_msg} [Y/N]: ', validator=validator)
|
||||
if response.upper().startswith('Y'):
|
||||
LOG.info('%sYes', prompt_msg)
|
||||
LOG.info('%s Yes', prompt_msg)
|
||||
return True
|
||||
if response.upper().startswith('N'):
|
||||
LOG.info('%sNo', prompt_msg)
|
||||
LOG.info('%s No', prompt_msg)
|
||||
return False
|
||||
|
||||
# This shouldn't ever be reached
|
||||
|
|
|
|||
|
|
@ -40,8 +40,15 @@ def clear_pane(pane_id: str | None = None) -> None:
|
|||
run_program(cmd, check=False)
|
||||
|
||||
|
||||
def fix_layout(layout: dict[str, dict[str, Any]], forced: bool = False) -> None:
|
||||
"""Fix pane sizes based on layout."""
|
||||
def fix_layout(
|
||||
layout: dict[str, dict[str, Any]],
|
||||
clear_on_resize: bool = False,
|
||||
forced: bool = False,
|
||||
) -> None:
|
||||
"""Fix pane sizes based on layout.
|
||||
|
||||
NOTE: The magic +/- 1 values are for the split rows/columns.
|
||||
"""
|
||||
resize_kwargs = []
|
||||
|
||||
# Bail early
|
||||
|
|
@ -49,37 +56,58 @@ def fix_layout(layout: dict[str, dict[str, Any]], forced: bool = False) -> None:
|
|||
# Layout should be fine
|
||||
return
|
||||
|
||||
# Clear current pane if needed
|
||||
if clear_on_resize:
|
||||
clear_pane()
|
||||
|
||||
# Remove closed panes
|
||||
for data in layout.values():
|
||||
data['Panes'] = [pane for pane in data['Panes'] if poll_pane(pane)]
|
||||
|
||||
# Calc height for "floating" row
|
||||
# NOTE: We start with height +1 to account for the splits (i.e. splits = num rows - 1)
|
||||
floating_height = 1 + get_window_size()[1]
|
||||
for group in ('Title', 'Info', 'Current', 'Workers'):
|
||||
if layout[group]['Panes']:
|
||||
group_height = 1 + layout[group].get('height', 0)
|
||||
if group == 'Workers':
|
||||
group_height *= len(layout[group]['Panes'])
|
||||
floating_height -= group_height
|
||||
|
||||
# Update main panes
|
||||
for section, data in layout.items():
|
||||
# "Floating" pane(s)
|
||||
if 'height' not in data and section in ('Info', 'Current', 'Workers'):
|
||||
for pane_id in data['Panes']:
|
||||
resize_kwargs.append({'pane_id': pane_id, 'height': floating_height})
|
||||
|
||||
# Rest of the panes
|
||||
if section == 'Workers':
|
||||
# Skip for now
|
||||
# Calculate constraints
|
||||
avail_horizontal, avail_vertical = get_window_size()
|
||||
avail_vertical -= layout['Current'].get('height', 0)
|
||||
for group in ('Title', 'Info'):
|
||||
if not layout[group]['Panes']:
|
||||
continue
|
||||
if 'height' in data:
|
||||
for pane_id in data['Panes']:
|
||||
resize_kwargs.append({'pane_id': pane_id, 'height': data['height']})
|
||||
if 'width' in data:
|
||||
for pane_id in data['Panes']:
|
||||
resize_kwargs.append({'pane_id': pane_id, 'width': data['width']})
|
||||
avail_vertical -= layout[group].get('height', 0) + 1
|
||||
num_workers = len(layout['Workers']['Panes'])
|
||||
avail_vertical -= num_workers * (layout['Workers'].get('height', 0) + 1)
|
||||
avail_horizontal -= layout['Progress']['width'] + 1
|
||||
|
||||
# Fix heights
|
||||
for group, data in layout.items():
|
||||
if not data['Panes'] or group in ('Started', 'Progress'):
|
||||
continue
|
||||
resize_kwargs.append(
|
||||
{'pane_id': data['Panes'][0], 'height': data.get('height', avail_vertical)}
|
||||
)
|
||||
if group == 'Workers' and len(data['Panes']) > 1:
|
||||
for pane_id in data['Panes'][1:]:
|
||||
resize_kwargs.append(
|
||||
{'pane_id': pane_id, 'height': data.get('height', avail_vertical)}
|
||||
)
|
||||
|
||||
# Fix widths
|
||||
resize_kwargs.append(
|
||||
{'pane_id': layout['Progress']['Panes'][0], 'width': layout['Progress']['width']}
|
||||
)
|
||||
resize_kwargs.append(
|
||||
{'pane_id': layout['Started']['Panes'][0], 'height': layout['Started']['height']}
|
||||
)
|
||||
for group, data in layout.items():
|
||||
num_panes = len(data['Panes'])
|
||||
if num_panes < 2 or group not in ('Title', 'Info'):
|
||||
continue
|
||||
pane_width, remainder = divmod(avail_horizontal - (num_panes-1), num_panes)
|
||||
for pane_id in data['Panes']:
|
||||
new_width = pane_width
|
||||
if remainder > 0:
|
||||
new_width += 1
|
||||
remainder -= 1
|
||||
resize_kwargs.append({'pane_id': pane_id, 'width': new_width})
|
||||
|
||||
# Resize panes
|
||||
for kwargs in resize_kwargs:
|
||||
try:
|
||||
resize_pane(**kwargs)
|
||||
|
|
@ -87,41 +115,22 @@ def fix_layout(layout: dict[str, dict[str, Any]], forced: bool = False) -> None:
|
|||
# Assuming pane was closed just before resizing
|
||||
pass
|
||||
|
||||
# Update "group" panes widths
|
||||
for group in ('Title', 'Info'):
|
||||
num_panes = len(layout[group]['Panes'])
|
||||
if num_panes <= 1:
|
||||
continue
|
||||
width = int( (get_pane_size()[0] - (1 - num_panes)) / num_panes )
|
||||
for pane_id in layout[group]['Panes']:
|
||||
resize_pane(pane_id, width=width)
|
||||
if group == 'Title':
|
||||
# (re)fix Started pane
|
||||
resize_pane(layout['Started']['Panes'][0], width=layout['Started']['width'])
|
||||
|
||||
# Bail early
|
||||
if not (
|
||||
layout['Workers']['Panes']
|
||||
and 'height' in layout['Workers']
|
||||
and floating_height > 0
|
||||
):
|
||||
return
|
||||
|
||||
# Update worker heights
|
||||
for worker in reversed(layout['Workers']['Panes']):
|
||||
resize_pane(worker, height=layout['Workers']['height'])
|
||||
|
||||
|
||||
def get_pane_size(pane_id: str | None = None) -> tuple[int, int]:
|
||||
"""Get current or target pane size, returns tuple."""
|
||||
cmd = ['tmux', 'display', '-p']
|
||||
cmd = ['tmux', 'display-message', '-p']
|
||||
if pane_id:
|
||||
cmd.extend(['-t', pane_id])
|
||||
cmd.append('#{pane_width} #{pane_height}')
|
||||
|
||||
# Get resolution
|
||||
proc = run_program(cmd, check=False)
|
||||
width, height = proc.stdout.strip().split()
|
||||
try:
|
||||
width, height = proc.stdout.strip().split()
|
||||
except ValueError:
|
||||
# Assuming this is a race condition as it usually happens inside the
|
||||
# background fix layout loop
|
||||
return 0, 0
|
||||
width = int(width)
|
||||
height = int(height)
|
||||
|
||||
|
|
@ -131,7 +140,7 @@ def get_pane_size(pane_id: str | None = None) -> tuple[int, int]:
|
|||
|
||||
def get_window_size() -> tuple[int, int]:
|
||||
"""Get current window size, returns tuple."""
|
||||
cmd = ['tmux', 'display', '-p', '#{window_width} #{window_height}']
|
||||
cmd = ['tmux', 'display-message', '-p', '#{window_width} #{window_height}']
|
||||
|
||||
# Get resolution
|
||||
proc = run_program(cmd, check=False)
|
||||
|
|
@ -177,23 +186,13 @@ def layout_needs_fixed(layout: dict[str, dict[str, Any]]) -> bool:
|
|||
get_pane_size(pane)[0] != data['width'] for pane in data['Panes']
|
||||
)
|
||||
|
||||
# TODO: Re-enable?
|
||||
## Group panes
|
||||
#for group in ('Title', 'Info'):
|
||||
# num_panes = len(layout[group]['Panes'])
|
||||
# if num_panes <= 1:
|
||||
# continue
|
||||
# width = int( (get_pane_size()[0] - (1 - num_panes)) / num_panes )
|
||||
# for pane in layout[group]['Panes']:
|
||||
# needs_fixed = needs_fixed or abs(get_pane_size(pane)[0] - width) > 2
|
||||
|
||||
# Done
|
||||
return needs_fixed
|
||||
|
||||
|
||||
def poll_pane(pane_id: str) -> bool:
|
||||
"""Check if pane exists, returns bool."""
|
||||
cmd = ['tmux', 'list-panes', '-F', '#D']
|
||||
cmd = ['tmux', 'list-panes', '-F', '#{pane_id}']
|
||||
|
||||
# Get list of panes
|
||||
proc = run_program(cmd, check=False)
|
||||
|
|
@ -249,7 +248,7 @@ def prep_action(
|
|||
'cat',
|
||||
])
|
||||
elif watch_cmd == 'tail':
|
||||
action_cmd.extend(['tail', '-q', '-f'])
|
||||
action_cmd.extend(['tail', '-f'])
|
||||
action_cmd.append(watch_file)
|
||||
else:
|
||||
LOG.error('No action specified')
|
||||
|
|
@ -315,7 +314,7 @@ def split_window(
|
|||
target_id: str | None = None,
|
||||
**action) -> str:
|
||||
"""Split tmux window, run action, and return pane_id as str."""
|
||||
cmd = ['tmux', 'split-window', '-d', '-PF', '#D']
|
||||
cmd = ['tmux', 'split-window', '-d', '-PF', '#{pane_id}']
|
||||
|
||||
# Safety checks
|
||||
if not (lines or percent):
|
||||
|
|
@ -336,7 +335,7 @@ def split_window(
|
|||
if lines:
|
||||
cmd.extend(['-l', str(lines)])
|
||||
elif percent:
|
||||
cmd.extend(['-p', str(percent)])
|
||||
cmd.extend(['-l', f'{percent}%'])
|
||||
|
||||
# New pane action
|
||||
cmd.extend(prep_action(**action))
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ TMUX_LAYOUT = { # NOTE: This needs to be in order from top to bottom
|
|||
'Info': {'Panes': []},
|
||||
'Current': {'Panes': [environ.get('TMUX_PANE', None)]},
|
||||
'Workers': {'Panes': []},
|
||||
'Started': {'Panes': [], 'width': TMUX_SIDE_WIDTH},
|
||||
'Started': {'Panes': [], 'height': TMUX_TITLE_HEIGHT},
|
||||
'Progress': {'Panes': [], 'width': TMUX_SIDE_WIDTH},
|
||||
}
|
||||
|
||||
|
|
@ -31,11 +31,12 @@ TMUX_LAYOUT = { # NOTE: This needs to be in order from top to bottom
|
|||
class TUI():
|
||||
"""Object for tracking TUI elements."""
|
||||
def __init__(self, title_text: str | None = None):
|
||||
self.clear_on_resize = False
|
||||
self.layout: dict[str, dict[str, Any]] = deepcopy(TMUX_LAYOUT)
|
||||
self.side_width: int = TMUX_SIDE_WIDTH
|
||||
self.title_text: str = title_text if title_text else 'Title Text'
|
||||
self.title_text_line2: str = ''
|
||||
self.title_colors: list[str | None] = ['BLUE', None]
|
||||
self.title_colors: list[str] = ['BLUE', '']
|
||||
|
||||
# Init tmux and start a background process to maintain layout
|
||||
self.init_tmux()
|
||||
|
|
@ -47,7 +48,7 @@ class TUI():
|
|||
def add_info_pane(
|
||||
self,
|
||||
lines: int | None = None,
|
||||
percent: int | None = None,
|
||||
percent: int = 0,
|
||||
update_layout: bool = True,
|
||||
**tmux_args,
|
||||
) -> None:
|
||||
|
|
@ -117,7 +118,7 @@ class TUI():
|
|||
def add_worker_pane(
|
||||
self,
|
||||
lines: int | None = None,
|
||||
percent: int | None = None,
|
||||
percent: int = 0,
|
||||
update_layout: bool = True,
|
||||
**tmux_args,
|
||||
) -> None:
|
||||
|
|
@ -136,7 +137,7 @@ class TUI():
|
|||
tmux_args.update({
|
||||
'behind': False,
|
||||
'lines': lines,
|
||||
'percent': percent,
|
||||
'percent': percent if percent else None,
|
||||
'target_id': None,
|
||||
'vertical': True,
|
||||
})
|
||||
|
|
@ -145,8 +146,8 @@ class TUI():
|
|||
if update_layout:
|
||||
self.layout['Workers']['height'] = height
|
||||
|
||||
# Add pane
|
||||
self.layout['Workers']['Panes'].append(tmux.split_window(**tmux_args))
|
||||
# Add pane (ensure panes are sorted top to bottom)
|
||||
self.layout['Workers']['Panes'].insert(0, tmux.split_window(**tmux_args))
|
||||
|
||||
def clear_current_pane(self) -> None:
|
||||
"""Clear screen and history for current pane."""
|
||||
|
|
@ -159,7 +160,7 @@ class TUI():
|
|||
def fix_layout(self, forced: bool = True) -> None:
|
||||
"""Fix tmux layout based on self.layout."""
|
||||
try:
|
||||
tmux.fix_layout(self.layout, forced=forced)
|
||||
tmux.fix_layout(self.layout, clear_on_resize=self.clear_on_resize, forced=forced)
|
||||
except RuntimeError:
|
||||
# Assuming self.panes changed while running
|
||||
pass
|
||||
|
|
@ -179,6 +180,25 @@ class TUI():
|
|||
self.layout.clear()
|
||||
self.layout.update(deepcopy(TMUX_LAYOUT))
|
||||
|
||||
# Progress
|
||||
self.layout['Progress']['Panes'].append(tmux.split_window(
|
||||
lines=TMUX_SIDE_WIDTH,
|
||||
text=' ',
|
||||
))
|
||||
|
||||
# Started
|
||||
self.layout['Started']['Panes'].append(tmux.split_window(
|
||||
behind=True,
|
||||
lines=2,
|
||||
target_id=self.layout['Progress']['Panes'][0],
|
||||
text=ansi.color_string(
|
||||
['Started', time.strftime("%Y-%m-%d %H:%M %Z")],
|
||||
['BLUE', None],
|
||||
sep='\n',
|
||||
),
|
||||
vertical=True,
|
||||
))
|
||||
|
||||
# Title
|
||||
self.layout['Title']['Panes'].append(tmux.split_window(
|
||||
behind=True,
|
||||
|
|
@ -191,22 +211,8 @@ class TUI():
|
|||
),
|
||||
))
|
||||
|
||||
# Started
|
||||
self.layout['Started']['Panes'].append(tmux.split_window(
|
||||
lines=TMUX_SIDE_WIDTH,
|
||||
target_id=self.layout['Title']['Panes'][0],
|
||||
text=ansi.color_string(
|
||||
['Started', time.strftime("%Y-%m-%d %H:%M %Z")],
|
||||
['BLUE', None],
|
||||
sep='\n',
|
||||
),
|
||||
))
|
||||
|
||||
# Progress
|
||||
self.layout['Progress']['Panes'].append(tmux.split_window(
|
||||
lines=TMUX_SIDE_WIDTH,
|
||||
text=' ',
|
||||
))
|
||||
# Done
|
||||
sleep(0.2)
|
||||
|
||||
def remove_all_info_panes(self) -> None:
|
||||
"""Remove all info panes and update layout."""
|
||||
|
|
@ -222,6 +228,20 @@ class TUI():
|
|||
self.layout['Workers']['Panes'].clear()
|
||||
tmux.kill_pane(*panes)
|
||||
|
||||
def reset_title_pane(
|
||||
self,
|
||||
line1: str = 'Title Text',
|
||||
line2: str = '',
|
||||
colors: list[str] | None = None,
|
||||
) -> None:
|
||||
"""Remove all extra title panes, reset main title pane, and update layout."""
|
||||
colors = self.title_colors if colors is None else colors
|
||||
panes = self.layout['Title']['Panes'].copy()
|
||||
if len(panes) > 1:
|
||||
tmux.kill_pane(*panes[1:])
|
||||
self.layout['Title']['Panes'] = panes[:1]
|
||||
self.set_title(line1, line2, colors)
|
||||
|
||||
def set_current_pane_height(self, height: int) -> None:
|
||||
"""Set current pane height and update layout."""
|
||||
self.layout['Current']['height'] = height
|
||||
|
|
@ -357,18 +377,6 @@ def layout_needs_fixed(layout) -> bool:
|
|||
# Done
|
||||
return needs_fixed
|
||||
|
||||
def test() -> TUI:
|
||||
"""TODO: Deleteme"""
|
||||
ui = TUI()
|
||||
ui.add_info_pane(lines=10, text='Info One')
|
||||
ui.add_info_pane(lines=10, text='Info Two')
|
||||
ui.add_info_pane(lines=10, text='Info Three')
|
||||
ui.add_worker_pane(lines=3, text='Work One')
|
||||
ui.add_worker_pane(lines=3, text='Work Two')
|
||||
ui.add_worker_pane(lines=3, text='Work Three')
|
||||
ui.fix_layout()
|
||||
return ui
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("This file is not meant to be called directly.")
|
||||
|
|
|
|||
|
|
@ -80,6 +80,21 @@ function copy_live_env() {
|
|||
mkdir -p "$PROFILE_DIR/airootfs/usr/local/bin"
|
||||
rsync -aI "$ROOT_DIR/scripts/" "$PROFILE_DIR/airootfs/usr/local/bin/"
|
||||
|
||||
echo "Copying WizardKit UFD files..."
|
||||
rsync -aI --exclude="macOS-boot-icon.tar" "$ROOT_DIR/setup/ufd/" "$PROFILE_DIR/airootfs/usr/share/WizardKit/"
|
||||
tar xaf "$ROOT_DIR/setup/ufd/macOS-boot-icon.tar" -C "$PROFILE_DIR/airootfs/usr/share/WizardKit"
|
||||
cp "$ROOT_DIR/images/rEFInd.png" "$PROFILE_DIR/airootfs/usr/share/WizardKit/EFI/Boot/rEFInd.png"
|
||||
cp "$ROOT_DIR/images/Syslinux.png" "$PROFILE_DIR/airootfs/usr/share/WizardKit/syslinux/syslinux.png"
|
||||
|
||||
echo "Copying Memtest86+ files..."
|
||||
rsync -aI "/boot/memtest86+/memtest.bin" "$PROFILE_DIR/airootfs/usr/share/WizardKit/syslinux/"
|
||||
rsync -aI "/boot/memtest86+/memtest.efi" "$PROFILE_DIR/airootfs/usr/share/WizardKit/EFI/Memtest86+/"
|
||||
mv "$PROFILE_DIR/airootfs/usr/share/WizardKit/EFI/Memtest86+"/{memtest.efi,bootx64.efi}
|
||||
|
||||
# Pre-compile Python scripts
|
||||
unset PYTHONPYCACHEPREFIX
|
||||
python -m compileall "$PROFILE_DIR/airootfs/usr/local/bin/"
|
||||
|
||||
# Update profiledef.sh to set proper permissions for executable files
|
||||
for _file in $(find "$PROFILE_DIR/airootfs" -executable -type f | sed "s%$PROFILE_DIR/airootfs%%" | sort); do
|
||||
sed -i "\$i\ [\"$_file\"]=\"0:0:755\"" "$PROFILE_DIR/profiledef.sh"
|
||||
|
|
@ -112,48 +127,15 @@ function update_live_env() {
|
|||
username="tech"
|
||||
label="${KIT_NAME_SHORT}_LINUX"
|
||||
|
||||
# Boot config
|
||||
cp "$ROOT_DIR/images/Syslinux.png" "$PROFILE_DIR/syslinux/splash.png"
|
||||
sed -i -r "s/___+/${KIT_NAME_FULL}/" "$PROFILE_DIR/airootfs/usr/share/WizardKit/syslinux/syslinux.cfg"
|
||||
|
||||
# MOTD
|
||||
sed -i -r "s/KIT_NAME_SHORT/$KIT_NAME_SHORT/" "$PROFILE_DIR/profiledef.sh"
|
||||
sed -i -r "s/KIT_NAME_FULL/$KIT_NAME_SHORT/" "$PROFILE_DIR/profiledef.sh"
|
||||
sed -i -r "s/SUPPORT_URL/$KIT_NAME_SHORT/" "$PROFILE_DIR/profiledef.sh"
|
||||
|
||||
# Boot config (legacy)
|
||||
mkdir -p "$TEMP_DIR" 2>/dev/null
|
||||
git clone --depth=1 https://github.com/ipxe/wimboot "$TEMP_DIR/wimboot"
|
||||
rsync -aI "$TEMP_DIR/wimboot"/{LICENSE.txt,README.md,wimboot} "$PROFILE_DIR/syslinux/wimboot/"
|
||||
cp "$ROOT_DIR/images/Pxelinux.png" "$PROFILE_DIR/syslinux/pxelinux.png"
|
||||
cp "$ROOT_DIR/images/Syslinux.png" "$PROFILE_DIR/syslinux/syslinux.png"
|
||||
sed -i -r "s/__+/$KIT_NAME_FULL/" "$PROFILE_DIR/syslinux/syslinux.cfg"
|
||||
|
||||
# Boot config (UEFI)
|
||||
curl -Lo "$TEMP_DIR/refind.zip" "https://sourceforge.net/projects/refind/files/latest/download"
|
||||
7z x -aoa "$TEMP_DIR/refind.zip" -o"$TEMP_DIR/refind"
|
||||
cp "$ROOT_DIR/images/rEFInd.png" "$PROFILE_DIR/EFI/boot/rEFInd.png"
|
||||
cp "$TEMP_DIR/refind"/refind*/"refind/refind_x64.efi" "$PROFILE_DIR/EFI/boot/bootx64.efi"
|
||||
rsync -aI "$TEMP_DIR/refind"/refind*/refind/drivers_x64/ "$PROFILE_DIR/EFI/boot/drivers_x64/"
|
||||
rsync -aI "$TEMP_DIR/refind"/refind*/refind/icons/ "$PROFILE_DIR/EFI/boot/icons/"
|
||||
sed -i "s/%ARCHISO_LABEL%/${label}/" "$PROFILE_DIR/EFI/boot/refind.conf"
|
||||
|
||||
# Memtest86+ (Open Source)
|
||||
mkdir -p "$PROFILE_DIR/EFI/memtest86+"
|
||||
mkdir -p "$TEMP_DIR/memtest86+"
|
||||
curl -Lo "$TEMP_DIR/memtest86+/memtest86-binaries.zip" "https://memtest.org/download/v6.10/mt86plus_6.10.binaries.zip"
|
||||
7z e "$TEMP_DIR/memtest86+/memtest86-binaries.zip" -o"$TEMP_DIR/memtest86+" "memtest64.efi"
|
||||
mv "$TEMP_DIR/memtest86+/memtest64.efi" "$PROFILE_DIR/EFI/memtest86+/bootx64.efi"
|
||||
|
||||
# Memtest86 (Passmark)
|
||||
mkdir -p "$PROFILE_DIR/EFI/memtest86/Benchmark"
|
||||
mkdir -p "$TEMP_DIR/memtest86"
|
||||
curl -Lo "$TEMP_DIR/memtest86/memtest86-usb.zip" "https://www.memtest86.com/downloads/memtest86-usb.zip"
|
||||
7z e -aoa "$TEMP_DIR/memtest86/memtest86-usb.zip" -o"$TEMP_DIR/memtest86" "memtest86-usb.img"
|
||||
7z e -aoa "$TEMP_DIR/memtest86/memtest86-usb.img" -o"$TEMP_DIR/memtest86" "MemTest86.img"
|
||||
7z x -aoa "$TEMP_DIR/memtest86/MemTest86.img" -o"$TEMP_DIR/memtest86"
|
||||
rm "$TEMP_DIR/memtest86/EFI/BOOT/BOOTIA32.efi"
|
||||
mv "$TEMP_DIR/memtest86/EFI/BOOT/BOOTX64.efi" "$PROFILE_DIR/EFI/memtest86/bootx64.efi"
|
||||
mv "$TEMP_DIR/memtest86/EFI/BOOT"/* "$PROFILE_DIR/EFI/memtest86"/
|
||||
mv "$TEMP_DIR/memtest86/help"/* "$PROFILE_DIR/EFI/memtest86"/
|
||||
mv "$TEMP_DIR/memtest86/license.rtf" "$PROFILE_DIR/EFI/memtest86"/
|
||||
|
||||
# Hostname
|
||||
echo "$hostname" > "$PROFILE_DIR/airootfs/etc/hostname"
|
||||
echo "127.0.1.1 $hostname.localdomain $hostname" >> "$PROFILE_DIR/airootfs/etc/hosts"
|
||||
|
|
@ -172,9 +154,6 @@ function update_live_env() {
|
|||
# MOTD
|
||||
sed -i -r "s/_+/$KIT_NAME_FULL Linux Environment/" "$PROFILE_DIR/airootfs/etc/motd"
|
||||
|
||||
# Network
|
||||
ln -s "/run/systemd/resolve/stub-resolv.conf" "$PROFILE_DIR/airootfs/etc/resolv.conf"
|
||||
|
||||
# Oh My ZSH
|
||||
git clone --depth=1 https://github.com/robbyrussell/oh-my-zsh.git "$SKEL_DIR/.oh-my-zsh"
|
||||
rm -Rf "$SKEL_DIR/.oh-my-zsh/.git"
|
||||
|
|
@ -347,16 +326,6 @@ function build_iso() {
|
|||
-v "$PROFILE_DIR" \
|
||||
| tee -a "$LOG_DIR/$DATETIME.log"
|
||||
|
||||
# Build better ISO
|
||||
rsync -aI "$PROFILE_DIR/EFI/" "${ISO_DIR:-safety}/EFI/"
|
||||
rsync -aI --ignore-existing "$PROFILE_DIR/syslinux/" "${ISO_DIR:-safety}/syslinux/"
|
||||
## Sketchy bit ##
|
||||
. /usr/bin/mkarchiso -o "${OUT_DIR}" -w "${WORK_DIR}" "${PROFILE_DIR}"
|
||||
isofs_dir="${ISO_DIR}"
|
||||
image_name="${KIT_NAME_SHORT}-Linux-${DATE}-x86_64.iso"
|
||||
rm "${OUT_DIR}/${image_name}"
|
||||
_build_iso_image
|
||||
|
||||
# Cleanup
|
||||
echo "Removing temp files..."
|
||||
rm "$TEMP_DIR/Linux" -Rf | tee -a "$LOG_DIR/$DATETIME.log"
|
||||
|
|
|
|||
|
|
@ -6,10 +6,6 @@
|
|||
setlocal EnableDelayedExpansion
|
||||
title WizardKit: Build Tool
|
||||
call :CheckFlags %*
|
||||
rem TODO: Remove warning
|
||||
echo "Windows PE build is currently under development"
|
||||
echo " Proceeding will likely result in errors so be warned"
|
||||
pause
|
||||
call :CheckElevation || goto Exit
|
||||
call :FindKitsRoot || goto ErrorKitNotFound
|
||||
|
||||
|
|
@ -19,14 +15,8 @@ set "dandi_set_env=%adk_root%\Deployment Tools\DandISetEnv.bat"
|
|||
if not exist "%dandi_set_env%" (goto ErrorKitNotFound)
|
||||
call "%dandi_set_env%" || goto ErrorUnknown
|
||||
|
||||
:EnsureCRLF
|
||||
rem Rewrite main.py using PowerShell to have CRLF/`r`n lineendings
|
||||
set "script=%~dp0\.bin\Scripts\borrowed\set-eol.ps1"
|
||||
set "main=%~dp0\.bin\Scripts\settings\main.py"
|
||||
powershell -executionpolicy bypass -noprofile -file %script% -lineEnding win -file %main% || goto ErrorUnknown
|
||||
|
||||
:Launch
|
||||
set "script=%~dp0\.bin\Scripts\build_pe.ps1"
|
||||
set "script=%~dp0\pe\build_pe.ps1"
|
||||
powershell -executionpolicy bypass -noprofile -file %script% || goto ErrorUnknown
|
||||
goto Exit
|
||||
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ smartmontools-svn
|
|||
ttf-font-awesome-4
|
||||
udevil
|
||||
wd719x-firmware
|
||||
wimboot-bin
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ bc
|
|||
bind
|
||||
bluez
|
||||
bluez-utils
|
||||
bolt
|
||||
btrfs-progs
|
||||
cbatticon
|
||||
chntpw
|
||||
|
|
@ -31,15 +32,21 @@ dosfstools
|
|||
dunst
|
||||
e2fsprogs
|
||||
edk2-shell
|
||||
efibootmgr
|
||||
evince
|
||||
exfatprogs
|
||||
f2fs-tools
|
||||
fatresize
|
||||
feh
|
||||
ffmpeg
|
||||
firefox
|
||||
foot-terminfo
|
||||
gnome-keyring
|
||||
gnu-netcat
|
||||
gparted
|
||||
gpicview
|
||||
gptfdisk
|
||||
grub
|
||||
gsmartcontrol
|
||||
hardinfo-gtk3
|
||||
hexedit
|
||||
|
|
@ -50,6 +57,7 @@ intel-ucode
|
|||
iwd
|
||||
iwgtk
|
||||
jfsutils
|
||||
kitty-terminfo
|
||||
ldns
|
||||
leafpad
|
||||
less
|
||||
|
|
@ -57,65 +65,77 @@ lha
|
|||
libewf
|
||||
libinput
|
||||
libldm
|
||||
libusb-compat
|
||||
libxft
|
||||
linux
|
||||
linux-firmware
|
||||
linux-firmware-marvell
|
||||
lm_sensors
|
||||
lsscsi
|
||||
lvm2
|
||||
lzip
|
||||
man-db
|
||||
man-pages
|
||||
mdadm
|
||||
mediainfo
|
||||
memtest86+
|
||||
memtest86-efi
|
||||
mesa-demos
|
||||
mesa-utils
|
||||
mkinitcpio
|
||||
mkinitcpio-archiso
|
||||
mkinitcpio-nfs-utils
|
||||
mkvtoolnix-cli
|
||||
mprime-bin
|
||||
mpv
|
||||
mtools
|
||||
nano
|
||||
nbd
|
||||
ncdu
|
||||
ndisc6
|
||||
nfs-utils
|
||||
nmap
|
||||
noto-fonts
|
||||
noto-fonts-cjk
|
||||
ntfs-3g
|
||||
numlockx
|
||||
nvme-cli
|
||||
open-iscsi
|
||||
openbox
|
||||
openssh
|
||||
opensuperclone-git
|
||||
otf-font-awesome-4
|
||||
p7zip
|
||||
papirus-icon-theme
|
||||
parted
|
||||
perl
|
||||
picom
|
||||
pipes.sh
|
||||
pv
|
||||
python
|
||||
python-docopt
|
||||
python-prompt_toolkit
|
||||
python-psutil
|
||||
python-pytz
|
||||
python-requests
|
||||
qemu-guest-agent
|
||||
qemu-guest-agent
|
||||
reiserfsprogs
|
||||
refind
|
||||
reiserfsprogs
|
||||
rfkill
|
||||
rng-tools
|
||||
rofi
|
||||
rsync
|
||||
rxvt-unicode
|
||||
rxvt-unicode-terminfo
|
||||
sdparm
|
||||
smartmontools-svn
|
||||
sof-firmware
|
||||
speedtest-cli
|
||||
spice-vdagent
|
||||
squashfs-tools
|
||||
st
|
||||
sudo
|
||||
sysbench
|
||||
sysfsutils
|
||||
syslinux
|
||||
systemd-resolvconf
|
||||
systemd-sysvcompat
|
||||
terminus-font
|
||||
testdisk
|
||||
|
|
@ -125,6 +145,8 @@ tigervnc
|
|||
tint2
|
||||
tk
|
||||
tmux
|
||||
tpm2-tools
|
||||
tpm2-tss
|
||||
tree
|
||||
ttf-font-awesome-4
|
||||
ttf-hack
|
||||
|
|
@ -135,6 +157,8 @@ ufw
|
|||
unarj
|
||||
unrar
|
||||
unzip
|
||||
usb_modeswitch
|
||||
usbmuxd
|
||||
usbutils
|
||||
util-linux
|
||||
veracrypt
|
||||
|
|
@ -142,7 +166,9 @@ vim
|
|||
virtualbox-guest-utils
|
||||
volumeicon
|
||||
wd719x-firmware
|
||||
wezterm-terminfo
|
||||
which
|
||||
wimboot-bin
|
||||
wimlib
|
||||
wmctrl
|
||||
xarchiver
|
||||
|
|
@ -150,6 +176,7 @@ xf86-input-libinput
|
|||
xf86-video-amdgpu
|
||||
xf86-video-fbdev
|
||||
xf86-video-nouveau
|
||||
xf86-video-qxl
|
||||
xf86-video-vesa
|
||||
xfsprogs
|
||||
xorg-server
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ curl
|
|||
dos2unix
|
||||
git
|
||||
gtk3
|
||||
memtest86+
|
||||
memtest86+-efi
|
||||
p7zip
|
||||
perl-rename
|
||||
pv
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
LANG=en_US.UTF-8
|
||||
LANG=C.UTF-8
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# vim:set ft=sh
|
||||
# MODULES
|
||||
# The following modules are loaded before any boot hooks are
|
||||
# run. Advanced users may wish to specify all system modules
|
||||
# in this array. For instance:
|
||||
# MODULES=(piix ide_disk reiserfs)
|
||||
MODULES=()
|
||||
|
||||
# BINARIES
|
||||
# This setting includes any additional binaries a given user may
|
||||
# wish into the CPIO image. This is run last, so it may be used to
|
||||
# override the actual binaries included by a given hook
|
||||
# BINARIES are dependency parsed, so you may safely ignore libraries
|
||||
BINARIES=()
|
||||
|
||||
# FILES
|
||||
# This setting is similar to BINARIES above, however, files are added
|
||||
# as-is and are not parsed in any way. This is useful for config files.
|
||||
FILES=()
|
||||
|
||||
# HOOKS
|
||||
# This is the most important setting in this file. The HOOKS control the
|
||||
# modules and scripts added to the image, and what happens at boot time.
|
||||
# Order is important, and it is recommended that you do not change the
|
||||
# order in which HOOKS are added. Run 'mkinitcpio -H <hook name>' for
|
||||
# help on a given hook.
|
||||
# 'base' is _required_ unless you know precisely what you are doing.
|
||||
# 'udev' is _required_ in order to automatically load modules
|
||||
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
|
||||
# Examples:
|
||||
## This setup specifies all modules in the MODULES setting above.
|
||||
## No raid, lvm2, or encrypted root is needed.
|
||||
# HOOKS=(base)
|
||||
#
|
||||
## This setup will autodetect all modules for your system and should
|
||||
## work as a sane default
|
||||
# HOOKS=(base udev autodetect block filesystems)
|
||||
#
|
||||
## This setup will generate a 'full' image which supports most systems.
|
||||
## No autodetection is done.
|
||||
# HOOKS=(base udev block filesystems)
|
||||
#
|
||||
## This setup assembles a pata mdadm array with an encrypted root FS.
|
||||
## Note: See 'mkinitcpio -H mdadm' for more information on raid devices.
|
||||
# HOOKS=(base udev block mdadm encrypt filesystems)
|
||||
#
|
||||
## This setup loads an lvm2 volume group on a usb device.
|
||||
# HOOKS=(base udev block lvm2 filesystems)
|
||||
#
|
||||
## NOTE: If you have /usr on a separate partition, you MUST include the
|
||||
# usr, fsck and shutdown hooks.
|
||||
HOOKS=(base udev modconf memdisk archiso_shutdown archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs archiso_kms block filesystems keyboard)
|
||||
|
||||
# COMPRESSION
|
||||
# Use this to compress the initramfs image. By default, gzip compression
|
||||
# is used. Use 'cat' to create an uncompressed image.
|
||||
#COMPRESSION="gzip"
|
||||
#COMPRESSION="bzip2"
|
||||
#COMPRESSION="lzma"
|
||||
COMPRESSION="xz"
|
||||
#COMPRESSION="lzop"
|
||||
#COMPRESSION="lz4"
|
||||
#COMPRESSION="zstd"
|
||||
|
||||
# COMPRESSION_OPTIONS
|
||||
# Additional options for the compressor
|
||||
#COMPRESSION_OPTIONS=()
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
HOOKS=(base udev modconf kms memdisk archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs block filesystems keyboard)
|
||||
COMPRESSION="xz"
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# mkinitcpio preset file for the 'linux' package on archiso
|
||||
|
||||
PRESETS=('archiso')
|
||||
|
||||
ALL_kver='/boot/vmlinuz-linux'
|
||||
ALL_config='/etc/mkinitcpio.conf'
|
||||
|
||||
archiso_image="/boot/initramfs-linux.img"
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
# remove from airootfs!
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Type = Package
|
||||
Target = glibc
|
||||
|
||||
[Action]
|
||||
Description = Uncommenting en_US.UTF-8 locale and running locale-gen...
|
||||
When = PostTransaction
|
||||
Depends = glibc
|
||||
Depends = sed
|
||||
Depends = sh
|
||||
Exec = /bin/sh -c "sed -i 's/#\(en_US\.UTF-8\)/\1/' /etc/locale.gen && locale-gen"
|
||||
23
setup/linux/profile/airootfs/etc/resolv.conf
Normal file
23
setup/linux/profile/airootfs/etc/resolv.conf
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).
|
||||
# Do not edit.
|
||||
#
|
||||
# This file might be symlinked as /etc/resolv.conf. If you're looking at
|
||||
# /etc/resolv.conf and seeing this text, you have followed the symlink.
|
||||
#
|
||||
# This is a dynamic resolv.conf file for connecting local clients to the
|
||||
# internal DNS stub resolver of systemd-resolved. This file lists all
|
||||
# configured search domains.
|
||||
#
|
||||
# Run "resolvectl status" to see details about the uplink DNS servers
|
||||
# currently in use.
|
||||
#
|
||||
# Third party programs should typically not access this file directly, but only
|
||||
# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a
|
||||
# different way, replace this symlink by a static file or a different symlink.
|
||||
#
|
||||
# See man:systemd-resolved.service(8) for details about the supported modes of
|
||||
# operation for /etc/resolv.conf.
|
||||
|
||||
nameserver 127.0.0.53
|
||||
options edns0 trust-ad
|
||||
search .
|
||||
|
|
@ -12,7 +12,6 @@ alias fix-perms='find -type d -exec chmod 755 "{}" \; && find -type f -exec chmo
|
|||
alias hexedit='hexedit --color'
|
||||
alias hw-info='sudo hw-info | less -S'
|
||||
alias ip='ip -br -c'
|
||||
alias journalctl-datarec="echo -e 'Monitoring journal output...\n' && journalctl -kf | grep -Ei 'ata|nvme|scsi|sd[a..z]+|usb|comreset|critical|error'"
|
||||
alias less='less -S'
|
||||
alias ls='ls --color=auto'
|
||||
alias mkdir='mkdir -p'
|
||||
|
|
|
|||
|
|
@ -2,8 +2,17 @@
|
|||
#
|
||||
## Calculate DPI, update settings if necessary, then start desktop apps
|
||||
|
||||
MONITOR=$(xrandr --listmonitors | grep -E '^\s+[0-9]' | head -1 | sed -r 's/^.*\s+(.*)$/\1/')
|
||||
REGEX_XRANDR='^.* ([0-9]+)x([0-9]+)\+[0-9]+\+[0-9]+.* ([0-9]+)mm x ([0-9]+)mm.*$'
|
||||
|
||||
# Resize screen in VMs
|
||||
if lsmod | grep -Eq 'qxl|virtio_gpu'; then
|
||||
echo -n "Starting VM guest services..."
|
||||
spice-vdagent
|
||||
sleep 0.5
|
||||
xrandr --output "${MONITOR}" --auto
|
||||
fi
|
||||
|
||||
echo -n "Getting display details... "
|
||||
|
||||
# Get screen data
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
setterm -blank 0 -powerdown 0 2>/dev/null
|
||||
if [ "$(fgconsole 2>/dev/null)" -eq "1" ]; then
|
||||
# VM guest init
|
||||
if lsmod | grep -Eq 'qxl|virtio_gpu'; then
|
||||
systemctl start spice-vdagentd.service
|
||||
fi
|
||||
|
||||
# Set up teststation details
|
||||
$HOME/.setup_teststation
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
[Network]
|
||||
IPv6PrivacyExtensions=yes
|
||||
|
|
@ -1,10 +1,21 @@
|
|||
[Match]
|
||||
# Matching with "Type=ether" causes issues with containers because it also matches virtual Ethernet interfaces (veth*).
|
||||
# See https://bugs.archlinux.org/task/70892
|
||||
# Instead match by globbing the network interface name.
|
||||
Name=en*
|
||||
Name=eth*
|
||||
|
||||
[Network]
|
||||
DHCP=yes
|
||||
IPv6PrivacyExtensions=yes
|
||||
MulticastDNS=yes
|
||||
|
||||
[DHCP]
|
||||
RouteMetric=512
|
||||
# systemd-networkd does not set per-interface-type default route metrics
|
||||
# https://github.com/systemd/systemd/issues/17698
|
||||
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
|
||||
# Use values from NetworkManager. From nm_device_get_route_metric_default in
|
||||
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
|
||||
[DHCPv4]
|
||||
RouteMetric=100
|
||||
|
||||
[IPv6AcceptRA]
|
||||
RouteMetric=100
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
[Match]
|
||||
Name=wlp*
|
||||
Name=wlan*
|
||||
|
||||
[Network]
|
||||
DHCP=yes
|
||||
IPv6PrivacyExtensions=yes
|
||||
|
||||
[DHCP]
|
||||
RouteMetric=1024
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
[Match]
|
||||
Name=wl*
|
||||
|
||||
[Network]
|
||||
DHCP=yes
|
||||
MulticastDNS=yes
|
||||
|
||||
# systemd-networkd does not set per-interface-type default route metrics
|
||||
# https://github.com/systemd/systemd/issues/17698
|
||||
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
|
||||
# Use values from NetworkManager. From nm_device_get_route_metric_default in
|
||||
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
|
||||
[DHCPv4]
|
||||
RouteMetric=600
|
||||
|
||||
[IPv6AcceptRA]
|
||||
RouteMetric=600
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[Match]
|
||||
Name=ww*
|
||||
|
||||
[Network]
|
||||
DHCP=yes
|
||||
|
||||
# systemd-networkd does not set per-interface-type default route metrics
|
||||
# https://github.com/systemd/systemd/issues/17698
|
||||
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
|
||||
# Use values from NetworkManager. From nm_device_get_route_metric_default in
|
||||
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
|
||||
[DHCPv4]
|
||||
RouteMetric=700
|
||||
|
||||
[IPv6AcceptRA]
|
||||
RouteMetric=700
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# Default systemd-resolved configuration for archiso
|
||||
|
||||
[Resolve]
|
||||
MulticastDNS=yes
|
||||
|
|
@ -5,4 +5,4 @@ Description=Temporary /etc/pacman.d/gnupg directory
|
|||
What=tmpfs
|
||||
Where=/etc/pacman.d/gnupg
|
||||
Type=tmpfs
|
||||
Options=mode=0755
|
||||
Options=mode=0755,noswap
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
/usr/lib/systemd/system/rngd.service
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
[Unit]
|
||||
Description=Initializes Pacman keyring
|
||||
Wants=haveged.service
|
||||
After=haveged.service
|
||||
Requires=etc-pacman.d-gnupg.mount
|
||||
After=etc-pacman.d-gnupg.mount
|
||||
After=etc-pacman.d-gnupg.mount time-sync.target
|
||||
BindsTo=etc-pacman.d-gnupg.mount
|
||||
Before=archlinux-keyring-wkd-sync.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/bin/pacman-key --init
|
||||
ExecStart=/usr/bin/pacman-key --populate archlinux
|
||||
ExecStart=/usr/bin/pacman-key --populate
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
|||
4
setup/linux/profile/airootfs/root/.gnupg/scdaemon.conf
Normal file
4
setup/linux/profile/airootfs/root/.gnupg/scdaemon.conf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
disable-ccid
|
||||
disable-pinpad
|
||||
pcsc-driver /usr/lib/libpcsclite.so
|
||||
pcsc-shared
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
title %ARCHISO_LABEL%
|
||||
title %ARCHISO_LABEL%
|
||||
sort-key 01
|
||||
linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
|
||||
initrd /%INSTALL_DIR%/boot/intel-ucode.img
|
||||
initrd /%INSTALL_DIR%/boot/amd-ucode.img
|
||||
initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
options archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL%
|
||||
linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
|
||||
initrd /%INSTALL_DIR%/boot/intel-ucode.img
|
||||
initrd /%INSTALL_DIR%/boot/amd-ucode.img
|
||||
initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
options archisobasedir=%INSTALL_DIR% archisodevice=UUID=%ARCHISO_UUID%
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
title %ARCHISO_LABEL% (Copy to RAM)
|
||||
sort-key 02
|
||||
linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
|
||||
initrd /%INSTALL_DIR%/boot/intel-ucode.img
|
||||
initrd /%INSTALL_DIR%/boot/amd-ucode.img
|
||||
initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
options archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram
|
||||
109
setup/linux/profile/grub/grub.cfg
Normal file
109
setup/linux/profile/grub/grub.cfg
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# Load partition table and file system modules
|
||||
insmod part_gpt
|
||||
insmod part_msdos
|
||||
insmod fat
|
||||
insmod iso9660
|
||||
insmod ntfs
|
||||
insmod ntfscomp
|
||||
insmod exfat
|
||||
insmod udf
|
||||
|
||||
# Use graphics-mode output
|
||||
if loadfont "${prefix}/fonts/unicode.pf2" ; then
|
||||
insmod all_video
|
||||
set gfxmode="auto"
|
||||
terminal_input console
|
||||
terminal_output console
|
||||
fi
|
||||
|
||||
# Enable serial console
|
||||
insmod serial
|
||||
insmod usbserial_common
|
||||
insmod usbserial_ftdi
|
||||
insmod usbserial_pl2303
|
||||
insmod usbserial_usbdebug
|
||||
if serial --unit=0 --speed=115200; then
|
||||
terminal_input --append serial
|
||||
terminal_output --append serial
|
||||
fi
|
||||
|
||||
# Search for the ISO volume
|
||||
if [ -z "${ARCHISO_UUID}" ]; then
|
||||
if [ -z "${ARCHISO_HINT}" ]; then
|
||||
regexp --set=1:ARCHISO_HINT '^\(([^)]+)\)' "${cmdpath}"
|
||||
fi
|
||||
search --no-floppy --set=root --file '%ARCHISO_SEARCH_FILENAME%' --hint "${ARCHISO_HINT}"
|
||||
probe --set ARCHISO_UUID --fs-uuid "${root}"
|
||||
fi
|
||||
|
||||
# Get a human readable platform identifier
|
||||
if [ "${grub_platform}" == 'efi' ]; then
|
||||
archiso_platform='UEFI'
|
||||
if [ "${grub_cpu}" == 'x86_64' ]; then
|
||||
archiso_platform="x64 ${archiso_platform}"
|
||||
elif [ "${grub_cpu}" == 'i386' ]; then
|
||||
archiso_platform="IA32 ${archiso_platform}"
|
||||
else
|
||||
archiso_platform="${grub_cpu} ${archiso_platform}"
|
||||
fi
|
||||
elif [ "${grub_platform}" == 'pc' ]; then
|
||||
archiso_platform='BIOS'
|
||||
else
|
||||
archiso_platform="${grub_cpu} ${grub_platform}"
|
||||
fi
|
||||
|
||||
# Set default menu entry
|
||||
default=archlinux
|
||||
timeout=15
|
||||
timeout_style=menu
|
||||
|
||||
|
||||
# Menu entries
|
||||
|
||||
menuentry "%ARCHISO_LABEL% (${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' {
|
||||
set gfxpayload=keep
|
||||
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% archisodevice=UUID=${ARCHISO_UUID}
|
||||
initrd /%INSTALL_DIR%/boot/intel-ucode.img /%INSTALL_DIR%/boot/amd-ucode.img /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
||||
}
|
||||
|
||||
if [ "${grub_platform}" == 'efi' -a "${grub_cpu}" == 'x86_64' -a -f '/boot/memtest86+/memtest.efi' ]; then
|
||||
menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool {
|
||||
set gfxpayload=800x600,1024x768
|
||||
linux /boot/memtest86+/memtest.efi
|
||||
}
|
||||
fi
|
||||
if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then
|
||||
menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool {
|
||||
set gfxpayload=800x600,1024x768
|
||||
linux /boot/memtest86+/memtest
|
||||
}
|
||||
fi
|
||||
if [ "${grub_platform}" == 'efi' ]; then
|
||||
if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then
|
||||
menuentry 'UEFI Shell' --class efi {
|
||||
chainloader /shellx64.efi
|
||||
}
|
||||
elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then
|
||||
menuentry 'UEFI Shell' --class efi {
|
||||
chainloader /shellia32.efi
|
||||
}
|
||||
fi
|
||||
|
||||
menuentry 'UEFI Firmware Settings' --id 'uefi-firmware' {
|
||||
fwsetup
|
||||
}
|
||||
fi
|
||||
|
||||
menuentry 'System shutdown' --class shutdown --class poweroff {
|
||||
echo 'System shutting down...'
|
||||
halt
|
||||
}
|
||||
|
||||
menuentry 'System restart' --class reboot --class restart {
|
||||
echo 'System rebooting...'
|
||||
reboot
|
||||
}
|
||||
|
||||
|
||||
# GRUB init tune for accessibility
|
||||
play 600 988 1 1319 4
|
||||
73
setup/linux/profile/grub/loopback.cfg
Normal file
73
setup/linux/profile/grub/loopback.cfg
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# https://www.supergrubdisk.org/wiki/Loopback.cfg
|
||||
|
||||
# Search for the ISO volume
|
||||
search --no-floppy --set=archiso_img_dev --file "${iso_path}"
|
||||
probe --set archiso_img_dev_uuid --fs-uuid "${archiso_img_dev}"
|
||||
|
||||
# Get a human readable platform identifier
|
||||
if [ "${grub_platform}" == 'efi' ]; then
|
||||
archiso_platform='UEFI'
|
||||
if [ "${grub_cpu}" == 'x86_64' ]; then
|
||||
archiso_platform="x64 ${archiso_platform}"
|
||||
elif [ "${grub_cpu}" == 'i386' ]; then
|
||||
archiso_platform="IA32 ${archiso_platform}"
|
||||
else
|
||||
archiso_platform="${grub_cpu} ${archiso_platform}"
|
||||
fi
|
||||
elif [ "${grub_platform}" == 'pc' ]; then
|
||||
archiso_platform='BIOS'
|
||||
else
|
||||
archiso_platform="${grub_cpu} ${grub_platform}"
|
||||
fi
|
||||
|
||||
# Set default menu entry
|
||||
default=archlinux
|
||||
timeout=15
|
||||
timeout_style=menu
|
||||
|
||||
|
||||
# Menu entries
|
||||
|
||||
menuentry "%ARCHISO_LABEL% (${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' {
|
||||
set gfxpayload=keep
|
||||
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}"
|
||||
initrd /%INSTALL_DIR%/boot/intel-ucode.img /%INSTALL_DIR%/boot/amd-ucode.img /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
||||
}
|
||||
|
||||
if [ "${grub_platform}" == 'efi' -a "${grub_cpu}" == 'x86_64' -a -f '/boot/memtest86+/memtest.efi' ]; then
|
||||
menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool {
|
||||
set gfxpayload=800x600,1024x768
|
||||
linux /boot/memtest86+/memtest.efi
|
||||
}
|
||||
fi
|
||||
if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then
|
||||
menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool {
|
||||
set gfxpayload=800x600,1024x768
|
||||
linux /boot/memtest86+/memtest
|
||||
}
|
||||
fi
|
||||
if [ "${grub_platform}" == 'efi' ]; then
|
||||
if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then
|
||||
menuentry 'UEFI Shell' --class efi {
|
||||
chainloader /shellx64.efi
|
||||
}
|
||||
elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then
|
||||
menuentry 'UEFI Shell' --class efi {
|
||||
chainloader /shellia32.efi
|
||||
}
|
||||
fi
|
||||
|
||||
menuentry 'UEFI Firmware Settings' --id 'uefi-firmware' {
|
||||
fwsetup
|
||||
}
|
||||
fi
|
||||
|
||||
menuentry 'System shutdown' --class shutdown --class poweroff {
|
||||
echo 'System shutting down...'
|
||||
halt
|
||||
}
|
||||
|
||||
menuentry 'System restart' --class reboot --class restart {
|
||||
echo 'System rebooting...'
|
||||
reboot
|
||||
}
|
||||
|
|
@ -8,16 +8,19 @@ iso_application="KIT_NAME_FULL Linux Environment"
|
|||
iso_version="$(date +%Y-%m-%d)"
|
||||
install_dir="arch"
|
||||
buildmodes=('iso')
|
||||
bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito')
|
||||
bootmodes=('bios.syslinux.mbr' 'bios.syslinux.eltorito'
|
||||
'uefi-ia32.grub.esp' 'uefi-x64.grub.esp'
|
||||
'uefi-ia32.grub.eltorito' 'uefi-x64.grub.eltorito')
|
||||
arch="x86_64"
|
||||
pacman_conf="pacman.conf"
|
||||
airootfs_image_type="squashfs"
|
||||
airootfs_image_tool_options=('-comp' 'xz' '-Xbcj' 'x86' '-b' '1M' '-Xdict-size' '1M')
|
||||
file_permissions=(
|
||||
["/root"]="0:0:750"
|
||||
["/etc/shadow"]="0:0:400"
|
||||
["/etc/gshadow"]="0:0:400"
|
||||
["/etc/shadow"]="0:0:400"
|
||||
["/etc/skel/.ssh"]="0:0:700"
|
||||
["/etc/skel/.ssh/authorized_keys"]="0:0:600"
|
||||
["/etc/skel/.ssh/id_rsa"]="0:0:600"
|
||||
["/root"]="0:0:750"
|
||||
["/root/.gnupg"]="0:0:700"
|
||||
)
|
||||
|
|
|
|||
28
setup/linux/profile/syslinux/archiso_head.cfg
Normal file
28
setup/linux/profile/syslinux/archiso_head.cfg
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
SERIAL 0 115200
|
||||
UI vesamenu.c32
|
||||
MENU TITLE Arch Linux
|
||||
MENU BACKGROUND splash.png
|
||||
|
||||
MENU WIDTH 78
|
||||
MENU MARGIN 4
|
||||
MENU ROWS 7
|
||||
MENU VSHIFT 10
|
||||
MENU TABMSGROW 14
|
||||
MENU CMDLINEROW 14
|
||||
MENU HELPMSGROW 16
|
||||
MENU HELPMSGENDROW 29
|
||||
|
||||
# Refer to https://wiki.syslinux.org/wiki/index.php/Comboot/menu.c32
|
||||
|
||||
MENU COLOR border 30;44 #40ffffff #a0000000 std
|
||||
MENU COLOR title 1;36;44 #9033ccff #a0000000 std
|
||||
MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all
|
||||
MENU COLOR unsel 37;44 #50ffffff #a0000000 std
|
||||
MENU COLOR help 37;40 #c0ffffff #a0000000 std
|
||||
MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std
|
||||
MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std
|
||||
MENU COLOR msg07 37;40 #90ffffff #a0000000 std
|
||||
MENU COLOR tabmsg 31;40 #30ffffff #00000000 std
|
||||
|
||||
MENU CLEAR
|
||||
MENU IMMEDIATE
|
||||
32
setup/linux/profile/syslinux/archiso_pxe-linux.cfg
Normal file
32
setup/linux/profile/syslinux/archiso_pxe-linux.cfg
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
LABEL arch64_nbd
|
||||
TEXT HELP
|
||||
Boot %ARCHISO_LABEL% using NBD.
|
||||
* HW diagnostics, file-based backups, data recovery, etc
|
||||
ENDTEXT
|
||||
MENU LABEL %ARCHISO_LABEL% (NBD)
|
||||
LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
|
||||
INITRD ::/%INSTALL_DIR%/boot/intel-ucode.img,::/%INSTALL_DIR%/boot/amd-ucode.img,::/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
APPEND archisobasedir=%INSTALL_DIR% archisodevice=UUID=%ARCHISO_UUID% archiso_nbd_srv=${pxeserver} cms_verify=y
|
||||
SYSAPPEND 3
|
||||
|
||||
LABEL arch64_nfs
|
||||
TEXT HELP
|
||||
Boot %ARCHISO_LABEL% using NFS.
|
||||
* HW diagnostics, file-based backups, data recovery, etc
|
||||
ENDTEXT
|
||||
MENU LABEL %ARCHISO_LABEL% (NFS)
|
||||
LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
|
||||
INITRD ::/%INSTALL_DIR%/boot/intel-ucode.img,::/%INSTALL_DIR%/boot/amd-ucode.img,::/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
APPEND archisobasedir=%INSTALL_DIR% archiso_nfs_srv=${pxeserver}:/run/archiso/bootmnt cms_verify=y
|
||||
SYSAPPEND 3
|
||||
|
||||
LABEL arch64_http
|
||||
TEXT HELP
|
||||
Boot %ARCHISO_LABEL% using HTTP.
|
||||
* HW diagnostics, file-based backups, data recovery, etc
|
||||
ENDTEXT
|
||||
MENU LABEL %ARCHISO_LABEL% (HTTP)
|
||||
LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
|
||||
INITRD ::/%INSTALL_DIR%/boot/intel-ucode.img,::/%INSTALL_DIR%/boot/amd-ucode.img,::/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ cms_verify=y
|
||||
SYSAPPEND 3
|
||||
5
setup/linux/profile/syslinux/archiso_pxe.cfg
Normal file
5
setup/linux/profile/syslinux/archiso_pxe.cfg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
INCLUDE archiso_head.cfg
|
||||
|
||||
INCLUDE archiso_pxe-linux.cfg
|
||||
|
||||
INCLUDE archiso_tail.cfg
|
||||
9
setup/linux/profile/syslinux/archiso_sys-linux.cfg
Normal file
9
setup/linux/profile/syslinux/archiso_sys-linux.cfg
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
LABEL arch64
|
||||
TEXT HELP
|
||||
Boot %ARCHISO_LABEL% on BIOS.
|
||||
* HW diagnostics, file-based backups, data recovery, etc
|
||||
ENDTEXT
|
||||
MENU LABEL %ARCHISO_LABEL% (BIOS)
|
||||
LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
|
||||
INITRD /%INSTALL_DIR%/boot/intel-ucode.img,/%INSTALL_DIR%/boot/amd-ucode.img,/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
APPEND archisobasedir=%INSTALL_DIR% archisodevice=UUID=%ARCHISO_UUID%
|
||||
8
setup/linux/profile/syslinux/archiso_sys.cfg
Normal file
8
setup/linux/profile/syslinux/archiso_sys.cfg
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
INCLUDE archiso_head.cfg
|
||||
|
||||
DEFAULT arch64
|
||||
TIMEOUT 150
|
||||
|
||||
INCLUDE archiso_sys-linux.cfg
|
||||
|
||||
INCLUDE archiso_tail.cfg
|
||||
35
setup/linux/profile/syslinux/archiso_tail.cfg
Normal file
35
setup/linux/profile/syslinux/archiso_tail.cfg
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
LABEL existing
|
||||
TEXT HELP
|
||||
Boot an existing operating system.
|
||||
Press TAB to edit the disk and partition number to boot.
|
||||
ENDTEXT
|
||||
MENU LABEL Boot existing OS
|
||||
COM32 chain.c32
|
||||
APPEND hd0 0
|
||||
|
||||
# https://www.memtest.org/
|
||||
LABEL memtest
|
||||
MENU LABEL Run Memtest86+ (RAM test)
|
||||
LINUX /boot/memtest86+/memtest
|
||||
|
||||
# https://wiki.syslinux.org/wiki/index.php/Hdt_(Hardware_Detection_Tool)
|
||||
LABEL hdt
|
||||
MENU LABEL Hardware Information (HDT)
|
||||
COM32 hdt.c32
|
||||
APPEND modules_alias=hdt/modalias.gz pciids=hdt/pciids.gz
|
||||
|
||||
LABEL reboot
|
||||
TEXT HELP
|
||||
Reboot computer.
|
||||
The computer's firmware must support APM.
|
||||
ENDTEXT
|
||||
MENU LABEL Reboot
|
||||
COM32 reboot.c32
|
||||
|
||||
LABEL poweroff
|
||||
TEXT HELP
|
||||
Power off computer.
|
||||
The computer's firmware must support APM.
|
||||
ENDTEXT
|
||||
MENU LABEL Power Off
|
||||
COM32 poweroff.c32
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
LABEL wk_linux
|
||||
TEXT HELP
|
||||
A live Linux environment
|
||||
* HW diagnostics, file-based backups, data recovery, etc
|
||||
ENDTEXT
|
||||
MENU LABEL Linux
|
||||
LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
||||
INITRD /%INSTALL_DIR%/boot/intel-ucode.img,/%INSTALL_DIR%/boot/amd-ucode.img,/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram loglevel=3
|
||||
|
||||
LABEL wk_linux_cli
|
||||
TEXT HELP
|
||||
A live Linux environment (CLI)
|
||||
* HW diagnostics, file-based backups, data recovery, etc
|
||||
ENDTEXT
|
||||
MENU LABEL Linux (CLI)
|
||||
LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux
|
||||
INITRD /%INSTALL_DIR%/boot/intel-ucode.img,/%INSTALL_DIR%/boot/amd-ucode.img,/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img
|
||||
APPEND archisobasedir=%INSTALL_DIR% archisolabel=%ARCHISO_LABEL% copytoram nox
|
||||
SYSAPPEND 3
|
||||
|
||||
|
|
@ -1,53 +1,11 @@
|
|||
SERIAL 0 115200
|
||||
UI vesamenu.c32
|
||||
MENU TITLE _______
|
||||
MENU BACKGROUND syslinux.png
|
||||
DEFAULT select
|
||||
|
||||
MENU WIDTH 80
|
||||
MENU MARGIN 10
|
||||
MENU ROWS 15
|
||||
MENU VSHIFT 2
|
||||
MENU TABMSGROW 22
|
||||
MENU CMDLINEROW 22
|
||||
MENU HELPMSGROW 24
|
||||
MENU HELPMSGENDROW -1
|
||||
MENU TABMSG
|
||||
LABEL select
|
||||
COM32 whichsys.c32
|
||||
APPEND -pxe- pxe -sys- sys -iso- sys
|
||||
|
||||
# Refer to http://syslinux.zytor.com/wiki/index.php/Doc/menu
|
||||
LABEL pxe
|
||||
CONFIG archiso_pxe.cfg
|
||||
|
||||
MENU COLOR screen 30;44 #a0000000 #a0000000 none
|
||||
MENU COLOR border 30;44 #a0000000 #a0000000 none
|
||||
MENU COLOR title 1;36;44 #9033ccff #a0000000 none
|
||||
MENU COLOR sel 7;37;40 #e0ffffff #a0000000 std
|
||||
MENU COLOR disabled 37;44 #50ffffff #a0000000 none
|
||||
MENU COLOR unsel 37;44 #50ffffff #a0000000 none
|
||||
MENU COLOR help 37;40 #c0ffffff #a0000000 none
|
||||
MENU COLOR tabmsg 30;44 #a0000000 #a0000000 none
|
||||
MENU COLOR cmdmark 1;36;44 #9033ccff #a0000000 none
|
||||
MENU COLOR cmdline 37;40 #c0ffffff #a0000000 none
|
||||
MENU COLOR timeout_msg 37;40 #80ffffff #a0000000 none
|
||||
MENU COLOR timeout 1;37;40 #c0ffffff #a0000000 none
|
||||
MENU COLOR msg07 37;40 #90ffffff #a0000000 none
|
||||
MENU COLOR tabmsg 31;40 #30ffffff #a0000000 none
|
||||
|
||||
# Start entries
|
||||
MENU SEPARATOR
|
||||
|
||||
MENU CLEAR
|
||||
|
||||
DEFAULT wk_linux
|
||||
TIMEOUT 0
|
||||
|
||||
INCLUDE linux.cfg
|
||||
INCLUDE memtest.cfg
|
||||
#UFD-WINPE#INCLUDE winpe.cfg
|
||||
|
||||
MENU SEPARATOR
|
||||
|
||||
LABEL reboot
|
||||
MENU LABEL Reboot
|
||||
COM32 reboot.c32
|
||||
|
||||
LABEL poweroff
|
||||
MENU LABEL Power Off
|
||||
COM32 poweroff.c32
|
||||
LABEL sys
|
||||
CONFIG archiso_sys.cfg
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ elif [[ "${OS_VERSION:0:5}" == "10.15" ]]; then
|
|||
fi
|
||||
|
||||
# Python3 Packages
|
||||
pip3 install docopt mysql-connector NumPy psutil pylint pytz requests
|
||||
pip3 install mysql-connector NumPy psutil pylint pytz requests
|
||||
|
||||
git clone https://github.com/yuyichao/gnuplot-py gnuplot-py
|
||||
cd gnuplot-py
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# WizardKit: WinPE #
|
||||
|
||||
_Under construction_
|
||||
Requires ADK for Windows 10, version 2004
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
[LaunchApp]
|
||||
[LaunchApps]
|
||||
wpeinit
|
||||
wpeutil updatebootinfo
|
||||
cd /d "%SystemDrive%\.bin"
|
||||
"%SystemDrive%\.bin\ConEmu\ConEmu.exe", /cmd cmd /k cd "%SystemDrive%\.bin" & python "%SystemDrive%\.bin\Scripts\winpe_root_menu.py"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
@echo off
|
||||
python "%SystemDrive%\.bin\Scripts\winpe_root_menu.py"
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,56 +1,56 @@
|
|||
<?xml version="1.0" encoding="Windows-1252" ?>
|
||||
<NotepadPlus>
|
||||
<FindHistory nbMaxFindHistoryPath="10" nbMaxFindHistoryFilter="10" nbMaxFindHistoryFind="10" nbMaxFindHistoryReplace="10" matchWord="no" matchCase="no" wrap="yes" directionDown="yes" fifRecuisive="yes" fifInHiddenFolder="no" dlgAlwaysVisible="no" fifFilterFollowsDoc="no" fifFolderFollowsDoc="no" searchMode="0" transparencyMode="1" transparency="150" dotMatchesNewline="no" />
|
||||
<History nbMaxFile="10" inSubMenu="no" customLength="-1" />
|
||||
<GUIConfigs>
|
||||
<GUIConfig name="ToolBar" visible="no">standard</GUIConfig>
|
||||
<GUIConfig name="StatusBar">hide</GUIConfig>
|
||||
<GUIConfig name="TabBar" dragAndDrop="yes" drawTopBar="yes" drawInactiveTab="yes" reduce="yes" closeButton="yes" doubleClick2Close="no" vertical="no" multiLine="no" hide="no" quitOnEmpty="no" />
|
||||
<GUIConfig name="ScintillaViewsSplitter">vertical</GUIConfig>
|
||||
<GUIConfig name="UserDefineDlg" position="undocked">hide</GUIConfig>
|
||||
<GUIConfig name="TabSetting" replaceBySpace="yes" size="4" />
|
||||
<GUIConfig name="noUpdate" intervalDays="15" nextUpdateDate="20080426">no</GUIConfig>
|
||||
<GUIConfig name="Auto-detection">yes</GUIConfig>
|
||||
<GUIConfig name="CheckHistoryFiles">no</GUIConfig>
|
||||
<GUIConfig name="TrayIcon">no</GUIConfig>
|
||||
<GUIConfig name="MaitainIndent">yes</GUIConfig>
|
||||
<GUIConfig name="TagsMatchHighLight" TagAttrHighLight="yes" HighLightNonHtmlZone="no">yes</GUIConfig>
|
||||
<GUIConfig name="RememberLastSession">no</GUIConfig>
|
||||
<GUIConfig name="DetectEncoding">yes</GUIConfig>
|
||||
<GUIConfig name="NewDocDefaultSettings" format="0" encoding="4" lang="0" codepage="-1" openAnsiAsUTF8="yes" />
|
||||
<GUIConfig name="langsExcluded" gr0="0" gr1="0" gr2="0" gr3="0" gr4="0" gr5="0" gr6="0" gr7="0" langMenuCompact="yes" />
|
||||
<GUIConfig name="Print" lineNumber="yes" printOption="3" headerLeft="" headerMiddle="" headerRight="" footerLeft="" footerMiddle="" footerRight="" headerFontName="" headerFontStyle="0" headerFontSize="0" footerFontName="" footerFontStyle="0" footerFontSize="0" margeLeft="0" margeRight="0" margeTop="0" margeBottom="0" />
|
||||
<GUIConfig name="Backup" action="0" useCustumDir="no" dir="" isSnapshotMode="no" snapshotBackupTiming="7000" />
|
||||
<GUIConfig name="TaskList">yes</GUIConfig>
|
||||
<GUIConfig name="MRU">yes</GUIConfig>
|
||||
<GUIConfig name="URL">2</GUIConfig>
|
||||
<GUIConfig name="globalOverride" fg="no" bg="no" font="yes" fontSize="no" bold="no" italic="no" underline="no" />
|
||||
<GUIConfig name="auto-completion" autoCAction="3" triggerFromNbChar="1" autoCIgnoreNumbers="yes" funcParams="yes" />
|
||||
<GUIConfig name="auto-insert" parentheses="no" brackets="no" curlyBrackets="no" quotes="no" doubleQuotes="no" htmlXmlTag="no" />
|
||||
<GUIConfig name="sessionExt"></GUIConfig>
|
||||
<GUIConfig name="workspaceExt"></GUIConfig>
|
||||
<GUIConfig name="MenuBar">hide</GUIConfig>
|
||||
<GUIConfig name="Caret" width="1" blinkRate="600" />
|
||||
<GUIConfig name="ScintillaGlobalSettings" enableMultiSelection="no" />
|
||||
<GUIConfig name="openSaveDir" value="0" defaultDirPath="" />
|
||||
<GUIConfig name="titleBar" short="no" />
|
||||
<GUIConfig name="wordCharList" useDefault="yes" charsAdded="" />
|
||||
<GUIConfig name="delimiterSelection" leftmostDelimiter="40" rightmostDelimiter="41" delimiterSelectionOnEntireDocument="no" />
|
||||
<GUIConfig name="multiInst" setting="0" />
|
||||
<GUIConfig name="MISC" fileSwitcherWithoutExtColumn="no" backSlashIsEscapeCharacterForSql="yes" newStyleSaveDlg="no" isFolderDroppedOpenFiles="no" />
|
||||
<GUIConfig name="searchEngine" searchEngineChoice="1" searchEngineCustom="" />
|
||||
<GUIConfig name="SmartHighLight" matchCase="no" wholeWordOnly="no" useFindSettings="no" onAnotherView="no">yes</GUIConfig>
|
||||
<GUIConfig name="ScintillaPrimaryView" lineNumberMargin="show" bookMarkMargin="show" indentGuideLine="show" folderMarkStyle="box" lineWrapMethod="aligned" currentLineHilitingShow="show" scrollBeyondLastLine="no" disableAdvancedScrolling="no" wrapSymbolShow="hide" Wrap="no" borderEdge="yes" edge="no" edgeNbColumn="80" zoom="0" zoom2="0" whiteSpaceShow="hide" eolShow="hide" borderWidth="2" smoothFont="no" />
|
||||
<GUIConfig name="DockingManager" leftWidth="200" rightWidth="200" topHeight="200" bottomHeight="200">
|
||||
<ActiveTabs cont="0" activeTab="-1" />
|
||||
<ActiveTabs cont="1" activeTab="-1" />
|
||||
<ActiveTabs cont="2" activeTab="-1" />
|
||||
<ActiveTabs cont="3" activeTab="-1" />
|
||||
</GUIConfig>
|
||||
</GUIConfigs>
|
||||
<ProjectPanels>
|
||||
<ProjectPanel id="0" workSpaceFile="" />
|
||||
<ProjectPanel id="1" workSpaceFile="" />
|
||||
<ProjectPanel id="2" workSpaceFile="" />
|
||||
</ProjectPanels>
|
||||
</NotepadPlus>
|
||||
<?xml version="1.0" encoding="Windows-1252" ?>
|
||||
<NotepadPlus>
|
||||
<FindHistory nbMaxFindHistoryPath="10" nbMaxFindHistoryFilter="10" nbMaxFindHistoryFind="10" nbMaxFindHistoryReplace="10" matchWord="no" matchCase="no" wrap="yes" directionDown="yes" fifRecuisive="yes" fifInHiddenFolder="no" dlgAlwaysVisible="no" fifFilterFollowsDoc="no" fifFolderFollowsDoc="no" searchMode="0" transparencyMode="1" transparency="150" dotMatchesNewline="no" />
|
||||
<History nbMaxFile="10" inSubMenu="no" customLength="-1" />
|
||||
<GUIConfigs>
|
||||
<GUIConfig name="ToolBar" visible="no">standard</GUIConfig>
|
||||
<GUIConfig name="StatusBar">hide</GUIConfig>
|
||||
<GUIConfig name="TabBar" dragAndDrop="yes" drawTopBar="yes" drawInactiveTab="yes" reduce="yes" closeButton="yes" doubleClick2Close="no" vertical="no" multiLine="no" hide="no" quitOnEmpty="no" />
|
||||
<GUIConfig name="ScintillaViewsSplitter">vertical</GUIConfig>
|
||||
<GUIConfig name="UserDefineDlg" position="undocked">hide</GUIConfig>
|
||||
<GUIConfig name="TabSetting" replaceBySpace="yes" size="4" />
|
||||
<GUIConfig name="noUpdate" intervalDays="15" nextUpdateDate="20080426">no</GUIConfig>
|
||||
<GUIConfig name="Auto-detection">yes</GUIConfig>
|
||||
<GUIConfig name="CheckHistoryFiles">no</GUIConfig>
|
||||
<GUIConfig name="TrayIcon">no</GUIConfig>
|
||||
<GUIConfig name="MaitainIndent">yes</GUIConfig>
|
||||
<GUIConfig name="TagsMatchHighLight" TagAttrHighLight="yes" HighLightNonHtmlZone="no">yes</GUIConfig>
|
||||
<GUIConfig name="RememberLastSession">no</GUIConfig>
|
||||
<GUIConfig name="DetectEncoding">yes</GUIConfig>
|
||||
<GUIConfig name="NewDocDefaultSettings" format="0" encoding="4" lang="0" codepage="-1" openAnsiAsUTF8="yes" />
|
||||
<GUIConfig name="langsExcluded" gr0="0" gr1="0" gr2="0" gr3="0" gr4="0" gr5="0" gr6="0" gr7="0" langMenuCompact="yes" />
|
||||
<GUIConfig name="Print" lineNumber="yes" printOption="3" headerLeft="" headerMiddle="" headerRight="" footerLeft="" footerMiddle="" footerRight="" headerFontName="" headerFontStyle="0" headerFontSize="0" footerFontName="" footerFontStyle="0" footerFontSize="0" margeLeft="0" margeRight="0" margeTop="0" margeBottom="0" />
|
||||
<GUIConfig name="Backup" action="0" useCustumDir="no" dir="" isSnapshotMode="no" snapshotBackupTiming="7000" />
|
||||
<GUIConfig name="TaskList">yes</GUIConfig>
|
||||
<GUIConfig name="MRU">yes</GUIConfig>
|
||||
<GUIConfig name="URL">2</GUIConfig>
|
||||
<GUIConfig name="globalOverride" fg="no" bg="no" font="yes" fontSize="no" bold="no" italic="no" underline="no" />
|
||||
<GUIConfig name="auto-completion" autoCAction="3" triggerFromNbChar="1" autoCIgnoreNumbers="yes" funcParams="yes" />
|
||||
<GUIConfig name="auto-insert" parentheses="no" brackets="no" curlyBrackets="no" quotes="no" doubleQuotes="no" htmlXmlTag="no" />
|
||||
<GUIConfig name="sessionExt"></GUIConfig>
|
||||
<GUIConfig name="workspaceExt"></GUIConfig>
|
||||
<GUIConfig name="MenuBar">hide</GUIConfig>
|
||||
<GUIConfig name="Caret" width="1" blinkRate="600" />
|
||||
<GUIConfig name="ScintillaGlobalSettings" enableMultiSelection="no" />
|
||||
<GUIConfig name="openSaveDir" value="0" defaultDirPath="" />
|
||||
<GUIConfig name="titleBar" short="no" />
|
||||
<GUIConfig name="wordCharList" useDefault="yes" charsAdded="" />
|
||||
<GUIConfig name="delimiterSelection" leftmostDelimiter="40" rightmostDelimiter="41" delimiterSelectionOnEntireDocument="no" />
|
||||
<GUIConfig name="multiInst" setting="0" />
|
||||
<GUIConfig name="MISC" fileSwitcherWithoutExtColumn="no" backSlashIsEscapeCharacterForSql="yes" newStyleSaveDlg="no" isFolderDroppedOpenFiles="no" />
|
||||
<GUIConfig name="searchEngine" searchEngineChoice="1" searchEngineCustom="" />
|
||||
<GUIConfig name="SmartHighLight" matchCase="no" wholeWordOnly="no" useFindSettings="no" onAnotherView="no">yes</GUIConfig>
|
||||
<GUIConfig name="ScintillaPrimaryView" lineNumberMargin="show" bookMarkMargin="show" indentGuideLine="show" folderMarkStyle="box" lineWrapMethod="aligned" currentLineHilitingShow="show" scrollBeyondLastLine="no" disableAdvancedScrolling="no" wrapSymbolShow="hide" Wrap="no" borderEdge="yes" edge="no" edgeNbColumn="80" zoom="0" zoom2="0" whiteSpaceShow="hide" eolShow="hide" borderWidth="2" smoothFont="no" />
|
||||
<GUIConfig name="DockingManager" leftWidth="200" rightWidth="200" topHeight="200" bottomHeight="200">
|
||||
<ActiveTabs cont="0" activeTab="-1" />
|
||||
<ActiveTabs cont="1" activeTab="-1" />
|
||||
<ActiveTabs cont="2" activeTab="-1" />
|
||||
<ActiveTabs cont="3" activeTab="-1" />
|
||||
</GUIConfig>
|
||||
</GUIConfigs>
|
||||
<ProjectPanels>
|
||||
<ProjectPanel id="0" workSpaceFile="" />
|
||||
<ProjectPanel id="1" workSpaceFile="" />
|
||||
<ProjectPanel id="2" workSpaceFile="" />
|
||||
</ProjectPanels>
|
||||
</NotepadPlus>
|
||||
File diff suppressed because it is too large
Load diff
6
setup/pe/additions/Windows/System32/Winpeshl.ini
Normal file
6
setup/pe/additions/Windows/System32/Winpeshl.ini
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[LaunchApp]
|
||||
[LaunchApps]
|
||||
wpeinit
|
||||
wpeutil InitializeNetwork
|
||||
wpeutil UpdateBootInfo
|
||||
"%SystemDrive%\Program Files\ConEmu\ConEmu64.exe", /cmd cmd
|
||||
5
setup/pe/additions/Windows/System32/custom.doskey
Normal file
5
setup/pe/additions/Windows/System32/custom.doskey
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
notepad="%ProgramFiles%\NotepadPlusPlus\notepad++.exe" $*
|
||||
poweroff=wpeutil shutdown
|
||||
reboot=wpeutil reboot
|
||||
restart=wpeutil reboot
|
||||
shutdown=wpeutil shutdown
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
[CPU-Z]
|
||||
VERSION=1.7.7.0
|
||||
TextFontName=
|
||||
TextFontSize=14
|
||||
TextFontColor=000080
|
||||
LabelFontName=
|
||||
LabelFontSize=14
|
||||
ACPI=1
|
||||
PCI=1
|
||||
MaxPCIBus=256
|
||||
DMI=1
|
||||
Sensor=1
|
||||
SMBus=1
|
||||
Display=1
|
||||
UseDisplayAPI=1
|
||||
BusClock=1
|
||||
Chipset=1
|
||||
SPD=1
|
||||
XOC=0
|
||||
CheckUpdates=0
|
||||
|
|
@ -1,671 +0,0 @@
|
|||
[Benchmark_CPU]
|
||||
Intel Pentium-100=707
|
||||
Intel Pentium-120/Notebook=835
|
||||
Intel Pentium-166/QDI=1380
|
||||
Cyrix 6x86MX-PR300=1411
|
||||
AMD-K6-166/QDI=1482
|
||||
Intel Pentium MMX-200=1484
|
||||
Cyrix MII-PR333=1518
|
||||
Intel Mobile Pentium MMX-233=1642
|
||||
Intel Pentium Pro-166 Dual CPU=1679
|
||||
AMD-K6-200/DTK=1777
|
||||
AMD-K6-200/QDI=1778
|
||||
Intel Pentium Pro-200=1944
|
||||
AMD-K6-233/DTK=2067
|
||||
Intel P2-233/Siemens=2350
|
||||
VIA Cyrix III 533/133=2362
|
||||
Intel Celeron-266/BXmaster=2586
|
||||
Intel P2-266/Siemens=2603
|
||||
AMD-K6-2-300/PCChips M577=2655
|
||||
Intel Celeron 300=2883
|
||||
Intel Celeron-300/PCChips=2922
|
||||
AMD-K6-2-350/FIC=3092
|
||||
AMD-K6-III-400=3524
|
||||
AMD-K6-III-400/FIC VA-503A=3557
|
||||
Intel Celeron-366/BXmaster=3718
|
||||
Intel P2-400/Siemens=3886
|
||||
Intel Celeron-400/BXmaster=3890
|
||||
AMD-K6-2-450/FIC=3964
|
||||
AMD-K6-III-448/FIC VA-503A=3975
|
||||
AMD-K6-III-450=3978
|
||||
Intel Mobile P2-400/Scenic=4047
|
||||
Intel Celeron-413/BXmaster=4175
|
||||
Intel Celeron-433=4219
|
||||
Intel P3-450/CC820=4363
|
||||
Intel P3-450/Siemens=4372
|
||||
Intel Celeron-450=4555
|
||||
Intel Celeron-300A@467=4686
|
||||
Intel Celeron-466/BXmaster=4789
|
||||
Intel P3-500/GA-6BXDS=5021
|
||||
Intel Pentium III Xeon-550=5299
|
||||
Intel Celeron-525/BXmaster=5314
|
||||
Intel P3-550/Siemens=5543
|
||||
Intel Celeron-550/BXmaster=5579
|
||||
Intel Celeron-575/BXmaster=5845
|
||||
Intel Celeron-616/BXmaster=5999
|
||||
Intel P3-617/GA-BX2000=6241
|
||||
AMD Athlon-600/AMD-750=6303
|
||||
AMD Duron-600/KT133=6436
|
||||
Intel P3-650/BX=6497
|
||||
AMD Athlon-650/KX133=6749
|
||||
AMD Duron-650/KT133=6971
|
||||
Intel P3-700/BX=7013
|
||||
AMD Athlon-700/KX133=7185
|
||||
AMD Duron-700/KT133=7507
|
||||
Intel Celeron-815/BXmaster=7985
|
||||
AMD Athlon-750/KT133=8085
|
||||
AMD Athlon-800/AMD-750=8286
|
||||
AMD Duron-800/KT133=8580
|
||||
Intel P3-650@870/BX=8675
|
||||
AMD Duron-850/KT133=9120
|
||||
Intel P3-650@917/BX=9175
|
||||
AMD Duron-900/KT133=9654
|
||||
AMD Duron-928 (9x103)=9952
|
||||
Intel Celeron-566@1010=10115
|
||||
VIA Antaur-1000=6108
|
||||
VIA C3-1333=7601
|
||||
AMD Duron-950/KT133=10190
|
||||
AMD Athlon-1000/KT133=10734
|
||||
AMD Athlon-1200/KT133=12949
|
||||
AMD Athlon XP 1500+/KT133=14297
|
||||
AMD Athlon XP 2000+/KT133A=17691
|
||||
AMD Athlon XP 2200+/KT133A=19490
|
||||
AMD Athlon XP-M 2500+/KM400=19590
|
||||
AMD Athlon XP-M 3000+/SiS748=23391
|
||||
Intel P3-1000/i815=10381
|
||||
Intel P4-1600=6636
|
||||
Intel P4-1800=7445
|
||||
Intel P4-2000=8272
|
||||
Intel P4-2500=11051
|
||||
Intel Pentium-M ULV-1000=10515
|
||||
Intel Pentium-M-1300=13590
|
||||
Intel Pentium-M-1600=16856
|
||||
Intel Pentium-M 735=16958
|
||||
Intel Pentium-M 755=20008
|
||||
Intel Pentium-M 770=21163
|
||||
Intel P4-2800(noHT)/i875P=12399
|
||||
Intel P4-3066(noHT)/i845PE=13479
|
||||
Intel P4-3000E(noHT)/i915P=22136
|
||||
Intel P4-3000 530 (HT)=34013
|
||||
Intel P4-3200E(noHT)/i875P=23446
|
||||
Intel P4-3600E(noHT)/i925X=26424
|
||||
Intel Xeon-3800(HT)=55028
|
||||
AMD Athlon64 3200+=23814
|
||||
AMD Athlon64 3800+=28731
|
||||
AMD Athlon64 FX-53=28727
|
||||
AMD Opteron 248=25920
|
||||
AMD Turion64 ML-34+=18520
|
||||
AMD Turion64 X2 TL-60=47697
|
||||
AMD Athlon 64 X2 4400+=52867
|
||||
Intel Core Duo T2600 (1core)=20293
|
||||
Intel Core Duo T2600 (2core)=40849
|
||||
Intel Core 2 Duo E6700=51765
|
||||
Intel Core 2 Duo T7400=53238
|
||||
Transmeta Crusoe TM5800-1000=6382
|
||||
2xIntel Xeon 5150/5000P=131832
|
||||
4xIntel Xeon MP 7040=180052
|
||||
Intel Core 2 Extreme QX6700=129908
|
||||
AMD Phenom 9500=103687
|
||||
Intel Atom 230=15438
|
||||
Intel Core i5-520M=94834
|
||||
Intel Core i7-860=180329
|
||||
Intel Core i7-820QM=123279
|
||||
Intel Core i7-980X=347501
|
||||
Intel Core i5-2520M=111448
|
||||
Intel Core i7-3820=265424
|
||||
|
||||
[Benchmark_FPU]
|
||||
Intel Pentium-100=1109
|
||||
VIA Cyrix III 533/133=1327
|
||||
Intel Pentium 120/Notebook=1350
|
||||
Intel Pentium Pro-166 Dual CPU=1663
|
||||
Intel Pentium Pro-200=1934
|
||||
Cyrix 6x86MX-PR300=2304
|
||||
Intel P2-233/Siemens=2323
|
||||
AMD-K6-166/QDI=2533
|
||||
Cyrix MII-PR333=2585
|
||||
Intel Celeron-266/BXmaster=2630
|
||||
Intel Mobile Pentium MMX-233=2647
|
||||
Intel P2-266/Siemens=2662
|
||||
Intel Celeron-300=2862
|
||||
AMD-K6-200/DTK=2999
|
||||
AMD-K6-200/QDI=3041
|
||||
AMD-K6-233/DTK=3492
|
||||
Intel Celeron-366/BXmaster=3650
|
||||
Intel P2-400/Siemens=3968
|
||||
Intel Celeron-400/BXmaster=3972
|
||||
Intel Mobile P2-400/Scenic=3973
|
||||
Intel Celeron-413/BXmaster=4097
|
||||
Intel Celeron-433=4304
|
||||
Intel P3-450/CC820=4444
|
||||
Intel P3-450/Siemens=4452
|
||||
Intel Celeron-450=4472
|
||||
Intel Celeron-300A@467=4599
|
||||
AMD-K6-2-300/PCChips M577=4605
|
||||
Intel Celeron-466/BXmaster=4628
|
||||
Intel P3-500/GA-6BXDS=4958
|
||||
Intel Celeron-525/BXmaster=5215
|
||||
AMD-K6-2-350/FIC=5368
|
||||
Intel Pentium III Xeon-550=5417
|
||||
Intel P3-550/Siemens=5440
|
||||
Intel Celeron-550/BXmaster=5477
|
||||
Intel Celeron-575/BXmaster=5738
|
||||
Intel Celeron-616/BXmaster=5897
|
||||
Intel P3-617/GA-BX2000=6114
|
||||
AMD-K6-III-400/FIC VA-503A=6166
|
||||
AMD-K6-III-400=6169
|
||||
Intel P3-650/BX=6446
|
||||
AMD-K6-2-450/FIC=6876
|
||||
AMD-K6-III-448/FIC VA-503A=6893
|
||||
AMD-K6-III-450=6895
|
||||
Intel P3-700/BX=6942
|
||||
Intel Celeron-815/BXmaster=7799
|
||||
Intel P3-650@870/BX=8614
|
||||
Intel P3-650@917/BX=9080
|
||||
VIA C3-1333=3160
|
||||
AMD Duron-600/KT133=9132
|
||||
AMD Athlon-600/AMD-750=9231
|
||||
AMD Athlon-650/KX133=9888
|
||||
Intel Celeron-566@1010=9977
|
||||
AMD Athlon-700/KX133=10527
|
||||
AMD Athlon-750/KT133=11457
|
||||
AMD Athlon-800/AMD-750=12149
|
||||
AMD Duron-850/KT133=12954
|
||||
AMD Duron-900/KT133=13712
|
||||
AMD Duron-928 (9x103)=14150
|
||||
AMD Duron-950/KT133=14479
|
||||
AMD Athlon-1000/KT133=15252
|
||||
AMD Athlon-1200/KT133=18378
|
||||
AMD Athlon XP 1500+/KT133=20757
|
||||
AMD Athlon XP 1800+=23375
|
||||
AMD Athlon XP 2000+/KT133A=25693
|
||||
AMD Athlon XP 2200+/KT133A=28296
|
||||
AMD Athlon XP-M 2500+/KM400=28877
|
||||
AMD Athlon XP-M 3000+/SiS748=34104
|
||||
Intel P3-1000/i815=9813
|
||||
Intel P4-1600=3282
|
||||
Intel P4-1800=3833
|
||||
Intel P4-2000=4256
|
||||
Intel P4-2500=6020
|
||||
Intel Pentium-M ULV-1000=8547
|
||||
Intel Pentium-M-1300=11089
|
||||
Intel Pentium-M-1600=13614
|
||||
Intel Pentium-M 735=14211
|
||||
Intel Pentium-M 755=16772
|
||||
Intel Pentium-M 770=17807
|
||||
Intel P4-2800(noHT)/i875P=6799
|
||||
Intel P4-3066(noHT)/i845PE=7396
|
||||
Intel P4-3000 530 (HT)=9220
|
||||
Intel P4-3200E(noHT)/i875P=6578
|
||||
Intel P4-3600E(noHT)/i925X=8163
|
||||
Intel Xeon-3800(HT)=17241
|
||||
AMD Athlon64 3200+=31194
|
||||
AMD Athlon64 3800+=37379
|
||||
AMD Athlon64 FX-53=37426
|
||||
AMD Opteron 248=34115
|
||||
AMD Turion64 ML-34+=28056
|
||||
AMD Turion64 X2 TL-60=62143
|
||||
AMD Athlon 64 X2 4400+=68974
|
||||
Intel Core Duo T2600 (1core)=16967
|
||||
Intel Core Duo T2600 (2core)=34039
|
||||
Intel Core 2 Duo E6600=36031
|
||||
Intel Core 2 Duo E6700=40075
|
||||
Intel Core 2 Duo T7400=32659
|
||||
Transmeta Crusoe TM5800-1000=4251
|
||||
2xIntel Xeon 5150/5000P=80725
|
||||
4xIntel Xeon MP 7040=54379
|
||||
Intel Core 2 Extreme QX6700=80338
|
||||
AMD Phenom 9500=133430
|
||||
Intel Atom 230=10769
|
||||
Intel Core i5-520M=60634
|
||||
Intel Core i7-860=131820
|
||||
Intel Core i7-820QM=90751
|
||||
Intel Core i7-980X=215620
|
||||
Intel Core i5-2520M=55354
|
||||
Intel Core i7-3820=130252
|
||||
|
||||
[Benchmark_MMX]
|
||||
AMD-K6-166/QDI=909
|
||||
AMD-K6-200/QDI=1070
|
||||
Intel P2-266/440LX=1339
|
||||
VIA Cyrix III 533/133=1815
|
||||
Intel Pentium MMX-200=2041
|
||||
Intel Mobile Pentium MMX-233=2363
|
||||
Intel P2-233/440BX=2390
|
||||
Intel Celeron-300=2931
|
||||
Intel Celeron-366=3742
|
||||
Intel Celeron-450=4602
|
||||
Intel Celeron-300A@467=4737
|
||||
Intel P3-500/GA-6BXDS=5009
|
||||
AMD Duron-600/KT133=5454
|
||||
Intel P3-550/Siemens=5513
|
||||
AMD Athlon-650/KX133=5906
|
||||
AMD Athlon-700/Abit KA7=6356
|
||||
Intel P3-650/BX=6490
|
||||
AMD Duron-750/KT133=6823
|
||||
AMD Athlon-750/KT133=6846
|
||||
Intel P3-700/BX=7025
|
||||
AMD Duron-800/KT133=7277
|
||||
AMD Duron-850/KT133=7738
|
||||
AMD Duron-900/KT133=8192
|
||||
AMD Duron-928 (9x103)=8448
|
||||
AMD Duron-950/KT133=8645
|
||||
Intel P3-650@870/BX=8706
|
||||
AMD Athlon-1000/KT133=9110
|
||||
Intel P3-650@917/BX=9173
|
||||
Intel Celeron-566@1010=10080
|
||||
VIA C3-1333=6063
|
||||
AMD Athlon-1200/KT133=10998
|
||||
AMD Athlon XP 1500+/KT133=12125
|
||||
AMD Athlon XP 1800+=13642
|
||||
AMD Athlon XP 2000+/KT133A=15013
|
||||
AMD Athlon XP 2200+/KT133A=16516
|
||||
AMD Athlon XP-M 2500+/KM400=16858
|
||||
AMD Athlon XP-M 3000+/SiS748=20040
|
||||
Intel P3-1000=9903
|
||||
Intel P4-1600=14468
|
||||
Intel P4-1800=16319
|
||||
Intel P4-2000=18140
|
||||
Intel P4-2500=22681
|
||||
Intel Pentium-M ULV-1000=9937
|
||||
Intel Pentium-M-1300=12865
|
||||
Intel Pentium-M-1600=15835
|
||||
Intel Pentium-M 735=16839
|
||||
Intel Pentium-M 755=19869
|
||||
Intel Pentium-M 770=21149
|
||||
Intel P4-2800(noHT)/i875P=24478
|
||||
Intel P4-3066(noHT)/i845PE=26437
|
||||
Intel P4-3000 530 (HT)=27352
|
||||
Intel P4-3200E(noHT)/i875P=22592
|
||||
Intel P4-3600E(noHT)/i925X=25314
|
||||
Intel Xeon-3800(HT)=53268
|
||||
AMD Athlon64 3200+=18228
|
||||
AMD Athlon64 3800+=21859
|
||||
AMD Athlon64 FX-53=21856
|
||||
AMD Opteron 248=19926
|
||||
AMD Turion64 ML-34+=16403
|
||||
AMD Turion64 X2 TL-60=36363
|
||||
AMD Athlon 64 X2 4400+=40282
|
||||
Intel Core Duo T2600 (1core)=21423
|
||||
Intel Core Duo T2600 (2core)=42912
|
||||
Intel Core 2 Duo E6600=74154
|
||||
Intel Core 2 Duo E6700=82312
|
||||
Intel Core 2 Duo T7400=67321
|
||||
Transmeta Crusoe TM5800-1000=5272
|
||||
2xIntel Xeon 5150/5000P=51186
|
||||
4xIntel Xeon MP 7040=83086
|
||||
Intel Core 2 Extreme QX6700=165067
|
||||
AMD Phenom 9500=80202
|
||||
Intel Atom 230=14545
|
||||
Intel Core i5-520M=80822
|
||||
Intel Core i7-860=171336
|
||||
Intel Core i7-820QM=115063
|
||||
Intel Core i7-980X=261051
|
||||
Intel Core i5-2520M=81444
|
||||
Intel Core i7-3820=160178
|
||||
|
||||
[Benchmark_Memory]
|
||||
Intel Pentium-100/FPM=69
|
||||
Intel Pentium Pro-166 Dual CPU=78
|
||||
AMD-K6-166/QDI/EDO=85
|
||||
Intel Pentium MMX-200/EDO=92
|
||||
AMD-K6-200/QDI/EDO=93
|
||||
Intel Pentium MMX-233/PC66=101
|
||||
Intel P2-233/440BX/PC66=111
|
||||
VIA Cyrix III 533/133=114
|
||||
Intel P2-266/440BX/PC66=117
|
||||
AMD-K6-III-400=135
|
||||
Intel Celeron-366/PC66=163
|
||||
AMD Duron-600/KT133=173
|
||||
AMD Athlon-700/KX133/PC133=202
|
||||
AMD Athlon-650/KX133=205
|
||||
Intel P3-500/GA-6BXDS/PC100=209
|
||||
Intel P3-550/Siemens/PC100=215
|
||||
Intel Celeron-300A@467/PC66=209
|
||||
Intel Celeron-300/PC66=146
|
||||
Intel P3-650/BX/PC100=238
|
||||
Intel P3-700/BX/PC100=211
|
||||
AMD Athlon-750/KT133/PC133=214
|
||||
AMD Duron-750/KT133=263
|
||||
Intel Celeron-566@1010=273
|
||||
VIA C3-1333/CN400=223
|
||||
AMD Duron-950/KT133=275
|
||||
AMD Duron-928 (9x103)/KT133=292
|
||||
AMD Duron-1100/SiS745/DDR333=477
|
||||
AMD Athlon XP-M 2500+/DDR333=548
|
||||
Intel P3-650@917/FSB140=310
|
||||
Intel P3-1000/PC133=218
|
||||
Intel P4-1600/i850=1115
|
||||
Intel P4-2000/i850/PC800=1245
|
||||
Intel P4-1800/i845G/DDR266=867
|
||||
Intel P4-2500/i845/DDR266=757
|
||||
Intel Pentium-M-1600/DDR266=830
|
||||
Intel Pentium-M 735/855PM/DDR400=971
|
||||
Intel P4-3066/i845PE/DDR266=1028
|
||||
Intel P4-2800/i875P/2Ch/DDR400=2056
|
||||
Intel P4-3200E/i875P/2Ch/DDR400=2342
|
||||
Intel P4-3600E/i915P/DDR2-533=2556
|
||||
Intel P4-3600E/i925X/DDR2-533=2844
|
||||
Intel Xeon-3800/E7525/DDR2-400=1635
|
||||
AMD Athlon64 3200+/1Ch/DDR400=1266
|
||||
AMD Athlon64 3800+/2Ch/DDR400=2375
|
||||
AMD Athlon64 FX-53/2Ch/DDR400=2166
|
||||
AMD Opteron 248/DDR266=947
|
||||
AMD Turion64 ML-34+=1071
|
||||
Intel Core 2 Duo E6700/DDR2-800=2894
|
||||
Transmeta Crusoe TM5800-1000=337
|
||||
2xIntel Xeon 5150/5000P/DDR2-667F=2919
|
||||
4xIntel Xeon MP 7040=1721
|
||||
AMD Phenom 9500=1795
|
||||
Intel Atom 230/945/DDR2-800=1682
|
||||
Intel Core i5-520M=5235
|
||||
Intel Core i7-860/DDR3-667/2CH=6506
|
||||
Intel Core i7-820QM=5424
|
||||
Intel Core i7-980X=9343
|
||||
Intel Core i7-3820/DDR3-1600/4CH=13366
|
||||
|
||||
[Benchmark_Disk_ReadBurst]
|
||||
Fujitsu MPB3043ATU E/PIO=4.03
|
||||
Seagate ST38410A/PIO=4.33
|
||||
Maxtor 91021U2/PIO=4.61
|
||||
Maxtor 92041U4/PIO=4.82
|
||||
Quantum Fireball_TM2110S300X=6.83
|
||||
SEAGATE ST51080N=7.92
|
||||
Seagate ST31277A=8,37
|
||||
IBM DCAS-32160 S65A=8.65
|
||||
QUANTUM FIREBALL ST3.2A/PIO=14.74
|
||||
Seagate ST39102LW Cheetah=30.05
|
||||
IBM DJNA-370910/UDMA66=15.27
|
||||
Seagate ST34321A/UDMA33=21.03
|
||||
Seagate ST38421A=23.82
|
||||
Seagate ST34310A=23.88
|
||||
QUANTUM FIREBALL SE2.1A=26.43
|
||||
Maxtor 91021U2/UDMA33=29.13
|
||||
Maxtor 54098U8/UDMA33=29.5
|
||||
IBM DTTA-350430=29.7
|
||||
IBM-DPTA-371360=29.86
|
||||
Seagate ST320420A=47.3
|
||||
IBM-DJNA-371350=27.87
|
||||
IBM-DTLA-307030/ATA100=82.22
|
||||
SEAGATE Cheetah X15/RAID=137.08
|
||||
IBM Deskstar 60GXP/ATA100=81.98
|
||||
MAXTOR 4K020H1/ATA100=84.58
|
||||
Seagate ST317221A/UDMA66=42.03
|
||||
Maxtor 6E040L0=79.36
|
||||
Seagate ST380021A/ATA100=73.11
|
||||
HITACHI DK23EA-40=80.04
|
||||
WDC WD800JB/ATA100=85.71
|
||||
TOSHIBA MK4019GAX=83.60
|
||||
Maxtor MaxLine III SATA+NCQ=119.96
|
||||
ST312002 6AS=106.61
|
||||
Maxtor Atlas 10K5 73SCA=145.86
|
||||
WDC WD3200YS-01PGB0=167.33
|
||||
Hitachi HTE726040M9AT00=84.61
|
||||
Seagate ST3160827AS=120.88
|
||||
WDC WD5000AADS-00S9B0=122.87
|
||||
Hitachi HTS545032B9A=161.10
|
||||
Seagate ST1000DM003-9YN1=282.43
|
||||
|
||||
[Benchmark_Disk_ReadRandom]
|
||||
Hitachi HTE726040M9AT00=22.82
|
||||
Maxtor Atlas 10K5 73SCA=31.61
|
||||
Seagate ST3160827AS=32.26
|
||||
FUJITSU MHV2080BH=17.79
|
||||
TOSHIBA MK8034GSX=18.12
|
||||
ST916082 1AS=22.27
|
||||
WDC WD5000AADS-00S9B0=24.58
|
||||
Hitachi HTS545032B9A=24.72
|
||||
Seagate ST1000DM003-9YN1=37.09
|
||||
|
||||
[Benchmark_Disk_RandomAccess]
|
||||
SEAGATE ST51080N=20.96
|
||||
Quantum Fireball_TM2110S300X=20.74
|
||||
Seagate ST34321A/UDMA33=17.21
|
||||
Seagate ST38410A/PIO=17.17
|
||||
Seagate ST31277A=16.75
|
||||
Fujitsu MPB3043ATU E=16.18
|
||||
IBM DTTA-350430=16.5
|
||||
IBM DCAS-32160 S65A=15.95
|
||||
Maxtor 92041U4/PIO=15.81
|
||||
Seagate ST34310A=15.56
|
||||
Maxtor 91021U2/PIO=15.66
|
||||
Seagate ST38421A=15.71
|
||||
QUANTUM FIREBALL ST3.2A=15.50
|
||||
QUANTUM FIREBALL SE2.1A=14.94
|
||||
Maxtor 54098U8/UDMA33=13.77
|
||||
Seagate ST320420A=12.57
|
||||
IBM DJNA-370910/UDMA66=12.10
|
||||
Seagate ST39102LW Cheetah=8.78
|
||||
IBM-DPTA-371360=13.37
|
||||
IBM-DJNA-371350=13.38
|
||||
IBM-DTLA-307030/ATA100=12.44
|
||||
IBM-DTLA-307030/ATA100+AAM=22.34
|
||||
SEAGATE Cheetah X15/RAID=5.65
|
||||
IBM Deskstar 60GXP=12.70
|
||||
MAXTOR 4K020H1/ATA100=19.12
|
||||
Seagate ST317221A/UDMA66=16.60
|
||||
Maxtor 6E040L0=14.52
|
||||
Seagate ST380021A/ATA100=14.58
|
||||
HITACHI DK23EA-40=19.40
|
||||
WDC WD800JB/ATA100=13.61
|
||||
TOSHIBA MK4019GAX=18.61
|
||||
Maxtor MaxLine III SATA+NCQ=15.82
|
||||
ST312002 6AS=12.51
|
||||
Maxtor Atlas 10K5 73SCA=10.16
|
||||
WDC WD3200YS-01PGB0=13.16
|
||||
Hitachi HTE726040M9AT00=12.90
|
||||
Seagate ST3160827AS=11.65
|
||||
Seagate ST380215A=14.82
|
||||
WDC WD5000AADS-00S9B0=17.37
|
||||
Hitachi HTS545032B9A=22.16
|
||||
Seagate ST1000DM003-9YN1=15.53
|
||||
|
||||
[LogfileSettings]
|
||||
COMP=1
|
||||
COMP_SP=1
|
||||
COMP_Name=1
|
||||
COMP_Os=1
|
||||
COMP_User=0
|
||||
CPU=1
|
||||
CPU_Name=1
|
||||
CPU_ID=1
|
||||
CPU_Vendor=1
|
||||
CPU_Stepping=1
|
||||
CPU_Type=1
|
||||
CPU_BrandID=1
|
||||
CPU_PN=1
|
||||
CPU_Clock=1
|
||||
CPU_MaxFreq=1
|
||||
CPU_CacheL1=1
|
||||
CPU_CacheL2=1
|
||||
CPU_TLB_I=1
|
||||
CPU_TLB_D=1
|
||||
CPU_Features=1
|
||||
CPU_PIROM=1
|
||||
MEM=1
|
||||
MEM_TotalSize=1
|
||||
MEM_Timing=1
|
||||
MEM_Row=1
|
||||
MEM_Row_Size=1
|
||||
MEM_Row_Type=1
|
||||
MEM_Row_Speed=1
|
||||
MEM_Row_Model=1
|
||||
MEM_Row_ECC=1
|
||||
MEM_Row_Date=1
|
||||
MEM_Row_SN=1
|
||||
MEM_Row_Cfg=1
|
||||
MEM_Row_Latency=1
|
||||
MEM_Row_Features=1
|
||||
MEM_Row_iFeatures=1
|
||||
BUS=1
|
||||
BUS_PCI=1
|
||||
BUS_PCI_DevName=1
|
||||
BUS_PCI_DevNumber=1
|
||||
BUS_PCI_Resources=1
|
||||
BUS_PCI_Features=1
|
||||
BUS_PCI_DevSpecific=1
|
||||
BUS_PCIX_Features=1
|
||||
BUS_PCIe_Features=1
|
||||
BUS_PCI_DRV_INFO=1
|
||||
BUS_EISA=1
|
||||
DMI=1
|
||||
DMI_0=1
|
||||
DMI_1=1
|
||||
DMI_2=1
|
||||
DMI_3=1
|
||||
DMI_4=1
|
||||
DMI_5=1
|
||||
DMI_6=1
|
||||
DMI_7=1
|
||||
DMI_8=1
|
||||
DMI_9=1
|
||||
DMI_10=1
|
||||
DMI_11=1
|
||||
DMI_12=1
|
||||
DMI_13=1
|
||||
DMI_14=1
|
||||
DMI_15=1
|
||||
DMI_16=1
|
||||
DMI_17=1
|
||||
DMI_18=1
|
||||
DMI_19=1
|
||||
DMI_20=1
|
||||
DMI_21=1
|
||||
DMI_22=1
|
||||
DMI_23=1
|
||||
DMI_24=1
|
||||
DMI_25=1
|
||||
DMI_26=1
|
||||
DMI_27=1
|
||||
DMI_28=1
|
||||
DMI_29=1
|
||||
DMI_30=1
|
||||
DMI_31=1
|
||||
DMI_32=1
|
||||
DMI_33=1
|
||||
DMI_34=1
|
||||
DMI_35=1
|
||||
DMI_36=1
|
||||
DMI_37=1
|
||||
DMI_38=1
|
||||
DMI_39=1
|
||||
DMI_129=1
|
||||
DMI_130=1
|
||||
DMI_131=1
|
||||
VIDEO=1
|
||||
VIDEO_Chipset=1
|
||||
VIDEO_Memory=1
|
||||
VIDEO_Card=1
|
||||
VIDEO_Bus=1
|
||||
VIDEO_RAMDAC=1
|
||||
VIDEO_BIOSver=1
|
||||
VIDEO_Clock=1
|
||||
VIDEO_HWID=1
|
||||
VIDEO_DRV_INFO=1
|
||||
VIDEO_DirectX=1
|
||||
MON=1
|
||||
MON_Name=1
|
||||
MON_SN=1
|
||||
MON_Date=1
|
||||
MON_Dimensions=1
|
||||
MON_DisplayType=1
|
||||
MON_InputSignal=1
|
||||
MON_Gamma=1
|
||||
MON_DPMSinput=1
|
||||
MON_DPMSmodes=1
|
||||
MOBO=1
|
||||
MOBO_Model=1
|
||||
MOBO_Chipset=1
|
||||
MOBO_CompName=1
|
||||
MOBO_MachineType=1
|
||||
MOBO_Slots=1
|
||||
MOBO_BIOS_Manuf=1
|
||||
MOBO_BIOS_Date=1
|
||||
MOBO_PNP_Devs=1
|
||||
MOBO_PNP_Nodes=1
|
||||
MOBO_ACPI_Devs=1
|
||||
MOBO_ACPI_Enum=1
|
||||
DRIVE=1
|
||||
DRIVE_IDE=1
|
||||
DRIVE_IDE_Ctrller=1
|
||||
DRIVE_IDE_Channel=1
|
||||
DRIVE_IDE_Model=1
|
||||
DRIVE_IDE_Rev=1
|
||||
DRIVE_IDE_SN=1
|
||||
DRIVE_IDE_Capacity=1
|
||||
DRIVE_IDE_Geometry=1
|
||||
DRIVE_IDE_Cache=1
|
||||
DRIVE_IDE_Xfer=1
|
||||
DRIVE_IDE_BasicCapab=1
|
||||
DRIVE_IDE_ATA2Capab=1
|
||||
DRIVE_IDE_SMART=1
|
||||
DRIVE_SCSI=1
|
||||
DRIVE_SCSI_ID=1
|
||||
DRIVE_SCSI_Desc=1
|
||||
DRIVE_SCSI_Class=1
|
||||
DRIVE_Floppy=1
|
||||
NETWORK=1
|
||||
NETWORK_HWID=1
|
||||
NETWORK_DRV_INFO=1
|
||||
AUDIO=1
|
||||
AUDIO_DRV_INFO=1
|
||||
AUDIO_HWID=1
|
||||
PORTS=1
|
||||
BUS_USB=1
|
||||
BUS_USB_DRV_INFO=1
|
||||
BATTERY=1
|
||||
SENSORS=1
|
||||
|
||||
[Settings]
|
||||
HighestIdeAddress=0
|
||||
AcpiEnum=0
|
||||
SWSMI=1
|
||||
DebugMode=0
|
||||
SMBus=1
|
||||
TempScale=C
|
||||
AC97CodecID=1
|
||||
SkipProblematicPciDev=0
|
||||
GPUI2C=1
|
||||
LPC=1
|
||||
DefReportType=5
|
||||
TPM=0
|
||||
PCIdirect=1
|
||||
OpenSystemSummary=0
|
||||
RememberPreferences=1
|
||||
LargeFonts=0
|
||||
OpenSensors=0
|
||||
MinimalizeMainWnd=0
|
||||
MinimalizeSensors=0
|
||||
PersistentDriver=0
|
||||
UseHPET=1
|
||||
AutoUpdate=0
|
||||
GPUI2CNVAPI=1
|
||||
GPUI2CADL=0
|
||||
SensorsOnly=0
|
||||
AcpiEval=1
|
||||
CpuClkFromBusClk=1
|
||||
BusClkPolling=1
|
||||
SMBusAdrExclude=11111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000
|
||||
GPUI2CBusExclude=00000000
|
||||
SensorsSM=1
|
||||
IoctlKernel=0
|
||||
SummaryOnly=0
|
||||
WakeGPUs=1
|
||||
KeepTheme=0
|
||||
FlushBuffers=1
|
||||
iMEsupport=1
|
||||
GPUI2Ccaching=1
|
||||
CSMI_SAS_Support=1
|
||||
DebugDirect=1
|
||||
MinimalizeSensorsClose=0
|
||||
WakeGPUsExt=0
|
||||
PollSleepingGPUs=0
|
||||
ShowWelcomeAndProgress=1
|
||||
EnablePchTherm=0
|
||||
ReorderGPUs=1
|
||||
NvmlSupport=1
|
||||
DecimalSeparator=.
|
||||
ThousandsSeparator=,
|
||||
CsvSeparator=,
|
||||
MinimizeGraphs=1
|
||||
TextButtons=0
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
@echo off
|
||||
|
||||
start "" %SystemDrive%\.bin\NotepadPlusPlus\notepadplusplus.exe %2 %3 %4 %5 %6 %7 %8 %9
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
[Start]
|
||||
m_lang_id=1
|
||||
QDir_Id=0
|
||||
useColorStart=1
|
||||
Als=12
|
||||
designe_mode=2
|
||||
showCmd=3
|
||||
StartCrash=0
|
||||
default_tab=
|
||||
Max=1
|
||||
show_ext_in_type=1
|
||||
title_info=1
|
||||
adresbar_style=1
|
||||
useTreeColor=1
|
||||
useColor=1
|
||||
[Favoriten]
|
||||
Ordner=.\Favoriten\
|
||||
[Q]
|
||||
Link=.\Favoriten\Quick-Link\
|
||||
[Q-Dir]
|
||||
Lizenz=1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[Vorschau]
|
||||
Filter=*.avi;*.bmp;*.gif;*.ico;*.jpeg;*.jpg;*.mp*;*.pdf;*.png;*.wm*;
|
||||
[Filter2]
|
||||
0=#Hidden=1=-1=1=1=-1=0
|
||||
1=*.zip;*.rar;*.gz;*.7z;=1=00AA00=-1=1=-1=0
|
||||
2=*.mp*;*.avi;*.wma;=1=DD0058=-1=1=-1=0
|
||||
3=#DIR=1=008800=-1=1=-1=0
|
||||
4=*.jpg;*.jpeg;*.png,*.gif;*.bmp;*.ico=1=BB00BB=-1=1=-1=0
|
||||
5=*.html;*.htm;*.url=1=456789=-1=1=-1=0
|
||||
6=*.pl;*.cgi;*.php;*.pdf;*.doc;*.rtf;*.xls=1=BB8844=-1=1=-1=0
|
||||
7=*.cpp;*.hpp;*.h=1=DD0058=-1=1=-1=0
|
||||
8=*.exe;*.dll;*.bat=1=FF0000=-1=1=-1=0
|
||||
9=*=1=0000BB=-1=1=-1=0
|
||||
10=#BG=1=-1=-1=1=-1=0
|
||||
11=#BG-A=1=-1=-1=1=-1=0
|
||||
[Ordner]
|
||||
Filter=
|
||||
[Column_OS_6.1_Ploder1]
|
||||
Spatlen_::{20D04FE0-3AEA-1069-A2D8-08002B30309D}=%1C%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F1%F1%F1%F1%14%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D0%02%00%00%CC%02%00%00%31%53%50%53%05%D5%CD%D5%9C%2E%1B%10%93%97%08%00%2B%2C%F9%AE%83%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%46%00%4D%00%54%00%49%00%44%00%00%00%08%00%00%00%4E%00%00%00%7B%00%42%00%37%00%32%00%35%00%46%00%31%00%33%00%30%00%2D%00%34%00%37%00%45%00%46%00%2D%00%31%00%30%00%31%00%41%00%2D%00%41%00%35%00%46%00%31%00%2D%00%30%00%32%00%36%00%30%00%38%00%43%00%39%00%45%00%45%00%42%00%41%00%43%00%7D%00%00%00%00%00%33%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%44%00%69%00%72%00%65%00%63%00%74%00%69%00%6F%00%6E%00%00%00%13%00%00%00%01%00%00%00%5B%00%00%00%0A%00%00%00%00%53%00%6F%00%72%00%74%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%1C%00%00%00%01%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%01%00%00%00%25%00%00%00%14%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%56%00%69%00%65%00%77%00%00%00%0B%00%00%00%FF%FF%00%00%1B%00%00%00%0A%00%00%00%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%04%00%00%00%23%00%00%00%12%00%00%00%00%49%00%63%00%6F%00%6E%00%53%00%69%00%7A%00%65%00%00%00%13%00%00%00%10%00%00%00%BD%00%00%00%10%00%00%00%00%43%00%6F%00%6C%00%49%00%6E%00%66%00%6F%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%78%00%00%00%FD%DF%DF%FD%10%00%00%00%00%00%00%00%00%00%00%00%04%00%00%00%18%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%8C%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%04%00%00%00%AF%00%00%00%35%4B%17%9B%FF%40%D2%11%A2%7E%00%C0%4F%C3%08%71%03%00%00%00%70%00%00%00%35%4B%17%9B%FF%40%D2%11%A2%7E%00%C0%4F%C3%08%71%02%00%00%00%70%00%00%00%2F%00%00%00%1E%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%50%00%49%00%44%00%00%00%13%00%00%00%04%00%00%00%1F%00%00%00%0E%00%00%00%00%46%00%46%00%6C%00%61%00%67%00%73%00%00%00%13%00%00%00%05%00%20%40%31%00%00%00%20%00%00%00%00%4C%00%6F%00%67%00%69%00%63%00%61%00%6C%00%56%00%69%00%65%00%77%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%01%00%00%00%00%00%00%00%00%00%00%00|CODEMODE1|-1905896973|772
|
||||
Spatlen_291=%1C%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F1%F1%F1%F1%14%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D0%02%00%00%CC%02%00%00%31%53%50%53%05%D5%CD%D5%9C%2E%1B%10%93%97%08%00%2B%2C%F9%AE%83%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%46%00%4D%00%54%00%49%00%44%00%00%00%08%00%00%00%4E%00%00%00%7B%00%30%00%30%00%30%00%30%00%30%00%30%00%30%00%30%00%2D%00%30%00%30%00%30%00%30%00%2D%00%30%00%30%00%30%00%30%00%2D%00%30%00%30%00%30%00%30%00%2D%00%30%00%30%00%30%00%30%00%30%00%30%00%30%00%30%00%30%00%30%00%30%00%30%00%7D%00%00%00%00%00%33%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%44%00%69%00%72%00%65%00%63%00%74%00%69%00%6F%00%6E%00%00%00%13%00%00%00%01%00%00%00%5B%00%00%00%0A%00%00%00%00%53%00%6F%00%72%00%74%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%1C%00%00%00%01%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%01%00%00%00%25%00%00%00%14%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%56%00%69%00%65%00%77%00%00%00%0B%00%00%00%00%00%00%00%1B%00%00%00%0A%00%00%00%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%04%00%00%00%23%00%00%00%12%00%00%00%00%49%00%63%00%6F%00%6E%00%53%00%69%00%7A%00%65%00%00%00%13%00%00%00%10%00%00%00%BD%00%00%00%10%00%00%00%00%43%00%6F%00%6C%00%49%00%6E%00%66%00%6F%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%78%00%00%00%FD%DF%DF%FD%10%00%00%00%00%00%00%00%00%00%00%00%04%00%00%00%18%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%EE%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0E%00%00%00%69%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%04%00%00%00%91%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0C%00%00%00%46%00%00%00%2F%00%00%00%1E%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%50%00%49%00%44%00%00%00%13%00%00%00%00%00%00%00%1F%00%00%00%0E%00%00%00%00%46%00%46%00%6C%00%61%00%67%00%73%00%00%00%13%00%00%00%05%00%20%40%31%00%00%00%20%00%00%00%00%4C%00%6F%00%67%00%69%00%63%00%61%00%6C%00%56%00%69%00%65%00%77%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%01%00%00%00%00%00%00%00%00%00%00%00|CODEMODE1|-563719693|772
|
||||
[Column_OS_6.1_Ploder2]
|
||||
Spatlen_::{20D04FE0-3AEA-1069-A2D8-08002B30309D}=%1C%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F1%F1%F1%F1%14%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D0%02%00%00%CC%02%00%00%31%53%50%53%05%D5%CD%D5%9C%2E%1B%10%93%97%08%00%2B%2C%F9%AE%83%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%46%00%4D%00%54%00%49%00%44%00%00%00%08%00%00%00%4E%00%00%00%7B%00%42%00%37%00%32%00%35%00%46%00%31%00%33%00%30%00%2D%00%34%00%37%00%45%00%46%00%2D%00%31%00%30%00%31%00%41%00%2D%00%41%00%35%00%46%00%31%00%2D%00%30%00%32%00%36%00%30%00%38%00%43%00%39%00%45%00%45%00%42%00%41%00%43%00%7D%00%00%00%00%00%33%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%44%00%69%00%72%00%65%00%63%00%74%00%69%00%6F%00%6E%00%00%00%13%00%00%00%01%00%00%00%5B%00%00%00%0A%00%00%00%00%53%00%6F%00%72%00%74%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%1C%00%00%00%01%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%01%00%00%00%25%00%00%00%14%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%56%00%69%00%65%00%77%00%00%00%0B%00%00%00%FF%FF%00%00%1B%00%00%00%0A%00%00%00%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%04%00%00%00%23%00%00%00%12%00%00%00%00%49%00%63%00%6F%00%6E%00%53%00%69%00%7A%00%65%00%00%00%13%00%00%00%10%00%00%00%BD%00%00%00%10%00%00%00%00%43%00%6F%00%6C%00%49%00%6E%00%66%00%6F%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%78%00%00%00%FD%DF%DF%FD%10%00%00%00%00%00%00%00%00%00%00%00%04%00%00%00%18%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%8C%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%04%00%00%00%AF%00%00%00%35%4B%17%9B%FF%40%D2%11%A2%7E%00%C0%4F%C3%08%71%03%00%00%00%70%00%00%00%35%4B%17%9B%FF%40%D2%11%A2%7E%00%C0%4F%C3%08%71%02%00%00%00%70%00%00%00%2F%00%00%00%1E%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%50%00%49%00%44%00%00%00%13%00%00%00%04%00%00%00%1F%00%00%00%0E%00%00%00%00%46%00%46%00%6C%00%61%00%67%00%73%00%00%00%13%00%00%00%05%00%20%40%31%00%00%00%20%00%00%00%00%4C%00%6F%00%67%00%69%00%63%00%61%00%6C%00%56%00%69%00%65%00%77%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%01%00%00%00%00%00%00%00%00%00%00%00|CODEMODE1|-1905896973|772
|
||||
[Column_OS_6.1_Ploder3]
|
||||
Spatlen_::{20D04FE0-3AEA-1069-A2D8-08002B30309D}=%1C%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F1%F1%F1%F1%14%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D0%02%00%00%CC%02%00%00%31%53%50%53%05%D5%CD%D5%9C%2E%1B%10%93%97%08%00%2B%2C%F9%AE%83%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%46%00%4D%00%54%00%49%00%44%00%00%00%08%00%00%00%4E%00%00%00%7B%00%42%00%37%00%32%00%35%00%46%00%31%00%33%00%30%00%2D%00%34%00%37%00%45%00%46%00%2D%00%31%00%30%00%31%00%41%00%2D%00%41%00%35%00%46%00%31%00%2D%00%30%00%32%00%36%00%30%00%38%00%43%00%39%00%45%00%45%00%42%00%41%00%43%00%7D%00%00%00%00%00%33%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%44%00%69%00%72%00%65%00%63%00%74%00%69%00%6F%00%6E%00%00%00%13%00%00%00%01%00%00%00%5B%00%00%00%0A%00%00%00%00%53%00%6F%00%72%00%74%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%1C%00%00%00%01%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%01%00%00%00%25%00%00%00%14%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%56%00%69%00%65%00%77%00%00%00%0B%00%00%00%FF%FF%00%00%1B%00%00%00%0A%00%00%00%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%04%00%00%00%23%00%00%00%12%00%00%00%00%49%00%63%00%6F%00%6E%00%53%00%69%00%7A%00%65%00%00%00%13%00%00%00%10%00%00%00%BD%00%00%00%10%00%00%00%00%43%00%6F%00%6C%00%49%00%6E%00%66%00%6F%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%78%00%00%00%FD%DF%DF%FD%10%00%00%00%00%00%00%00%00%00%00%00%04%00%00%00%18%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%8C%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%04%00%00%00%AF%00%00%00%35%4B%17%9B%FF%40%D2%11%A2%7E%00%C0%4F%C3%08%71%03%00%00%00%70%00%00%00%35%4B%17%9B%FF%40%D2%11%A2%7E%00%C0%4F%C3%08%71%02%00%00%00%70%00%00%00%2F%00%00%00%1E%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%50%00%49%00%44%00%00%00%13%00%00%00%04%00%00%00%1F%00%00%00%0E%00%00%00%00%46%00%46%00%6C%00%61%00%67%00%73%00%00%00%13%00%00%00%05%00%20%40%31%00%00%00%20%00%00%00%00%4C%00%6F%00%67%00%69%00%63%00%61%00%6C%00%56%00%69%00%65%00%77%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%01%00%00%00%00%00%00%00%00%00%00%00|CODEMODE1|-1905896973|772
|
||||
[Column_OS_6.1_Ploder4]
|
||||
Spatlen_::{20D04FE0-3AEA-1069-A2D8-08002B30309D}=%1C%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F1%F1%F1%F1%14%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%D0%02%00%00%CC%02%00%00%31%53%50%53%05%D5%CD%D5%9C%2E%1B%10%93%97%08%00%2B%2C%F9%AE%83%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%46%00%4D%00%54%00%49%00%44%00%00%00%08%00%00%00%4E%00%00%00%7B%00%42%00%37%00%32%00%35%00%46%00%31%00%33%00%30%00%2D%00%34%00%37%00%45%00%46%00%2D%00%31%00%30%00%31%00%41%00%2D%00%41%00%35%00%46%00%31%00%2D%00%30%00%32%00%36%00%30%00%38%00%43%00%39%00%45%00%45%00%42%00%41%00%43%00%7D%00%00%00%00%00%33%00%00%00%22%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%44%00%69%00%72%00%65%00%63%00%74%00%69%00%6F%00%6E%00%00%00%13%00%00%00%01%00%00%00%5B%00%00%00%0A%00%00%00%00%53%00%6F%00%72%00%74%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%1C%00%00%00%01%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%01%00%00%00%25%00%00%00%14%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%56%00%69%00%65%00%77%00%00%00%0B%00%00%00%FF%FF%00%00%1B%00%00%00%0A%00%00%00%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%04%00%00%00%23%00%00%00%12%00%00%00%00%49%00%63%00%6F%00%6E%00%53%00%69%00%7A%00%65%00%00%00%13%00%00%00%10%00%00%00%BD%00%00%00%10%00%00%00%00%43%00%6F%00%6C%00%49%00%6E%00%66%00%6F%00%00%00%42%00%00%00%1E%00%00%00%70%00%72%00%6F%00%70%00%34%00%32%00%39%00%34%00%39%00%36%00%37%00%32%00%39%00%35%00%00%00%00%00%78%00%00%00%FD%DF%DF%FD%10%00%00%00%00%00%00%00%00%00%00%00%04%00%00%00%18%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%0A%00%00%00%8C%00%00%00%30%F1%25%B7%EF%47%1A%10%A5%F1%02%60%8C%9E%EB%AC%04%00%00%00%AF%00%00%00%35%4B%17%9B%FF%40%D2%11%A2%7E%00%C0%4F%C3%08%71%03%00%00%00%70%00%00%00%35%4B%17%9B%FF%40%D2%11%A2%7E%00%C0%4F%C3%08%71%02%00%00%00%70%00%00%00%2F%00%00%00%1E%00%00%00%00%47%00%72%00%6F%00%75%00%70%00%42%00%79%00%4B%00%65%00%79%00%3A%00%50%00%49%00%44%00%00%00%13%00%00%00%04%00%00%00%1F%00%00%00%0E%00%00%00%00%46%00%46%00%6C%00%61%00%67%00%73%00%00%00%13%00%00%00%05%00%20%40%31%00%00%00%20%00%00%00%00%4C%00%6F%00%67%00%69%00%63%00%61%00%6C%00%56%00%69%00%65%00%77%00%4D%00%6F%00%64%00%65%00%00%00%13%00%00%00%01%00%00%00%00%00%00%00%00%00%00%00|CODEMODE1|-1905896973|772
|
||||
[Programs_State]
|
||||
Disable=0
|
||||
[Quick-Links]
|
||||
WK=%systemdrive%/WK
|
||||
[Options]
|
||||
Start=7
|
||||
[X-Size]
|
||||
mode=1
|
||||
dig=0
|
||||
fld_size=1
|
||||
ths_sep=1
|
||||
type=0
|
||||
precent=1
|
||||
ff_cnt=1
|
||||
block_no_focus=1
|
||||
nosort_fld_size=1
|
||||
|
|
@ -6,23 +6,44 @@
|
|||
if (Test-Path Env:\DEBUG) {
|
||||
Set-PSDebug -Trace 1
|
||||
}
|
||||
$Host.UI.RawUI.WindowTitle = "Wizard Kit: Windows PE Build Tool"
|
||||
$WD = $(Split-Path $MyInvocation.MyCommand.Path)
|
||||
$Bin = (Get-Item $WD -Force).Parent.FullName
|
||||
$Root = (Get-Item $Bin -Force).Parent.FullName
|
||||
$Build = "$Root\BUILD_PE"
|
||||
$LogDir = "$Build\Logs"
|
||||
$Temp = "$Build\Temp"
|
||||
try {
|
||||
Import-Module -Name $Env:DISMRoot -ErrorAction "stop"
|
||||
}
|
||||
catch {
|
||||
Write-Host -ForegroundColor "Red" "ERROR: Failed to load DISM CmdLet"
|
||||
Abort
|
||||
}
|
||||
# Dirs
|
||||
$WorkingDir = $(Split-Path $MyInvocation.MyCommand.Path)
|
||||
$SetupDir = (Get-Item $WorkingDir -Force).Parent.FullName
|
||||
$RootDir = (Get-Item $SetupDir -Force).Parent.FullName
|
||||
$BuildDir = "$SetupDir\BUILD_PE"
|
||||
$OutDir = "$SetupDir\OUT_PE"
|
||||
$TempDir = "$BuildDir\temp"
|
||||
$MountDir = "$BuildDir\mount"
|
||||
$TargetDir = "$BuildDir\pe_files"
|
||||
# Misc
|
||||
$Arch = "amd64"
|
||||
$Date = Get-Date -UFormat "%Y-%m-%d"
|
||||
$Host.UI.RawUI.BackgroundColor = "Black"
|
||||
$Host.UI.RawUI.ForegroundColor = "White"
|
||||
$DISM = "{0}\DISM.exe" -f $Env:DISMRoot
|
||||
$HostSystem32 = "{0}\System32" -f $Env:SystemRoot
|
||||
$HostSysWOW64 = "{0}\SysWOW64" -f $Env:SystemRoot
|
||||
$DISM = "{0}\DISM.exe" -f $Env:DISMRoot
|
||||
#Enable TLS 1.2
|
||||
$KitNameFull = (Get-Content "$RootDir\scripts\wk\cfg\main.py" | Where-Object {$_ -imatch '^KIT_NAME_FULL'}) -ireplace '.*=.(.*).$', '$1'
|
||||
$KitNameShort = (Get-Content "$RootDir\scripts\wk\cfg\main.py" | Where-Object {$_ -imatch '^KIT_NAME_SHORT'}) -ireplace '.*=.(.*).$', '$1'
|
||||
# Set up UI
|
||||
$Host.UI.RawUI.WindowTitle = "${KitNameFull}: Windows PE Build Tool"
|
||||
$Host.UI.RawUI.BackgroundColor = "Black"
|
||||
$Host.UI.RawUI.ForegroundColor = "White"
|
||||
# Enable TLS 1.2
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
## Functions ##
|
||||
function Abort {
|
||||
Write-Host -ForegroundColor "Red" "`nAborted."
|
||||
WKPause "Press Enter to exit... "
|
||||
exit
|
||||
}
|
||||
|
||||
function Ask-User ($text = "Kotaero") {
|
||||
$text += " [Y/N]"
|
||||
while ($true) {
|
||||
|
|
@ -37,33 +58,36 @@ function Ask-User ($text = "Kotaero") {
|
|||
}
|
||||
$answer
|
||||
}
|
||||
function Abort {
|
||||
Write-Host -ForegroundColor "Red" "`nAborted."
|
||||
WKPause "Press Enter to exit... "
|
||||
exit
|
||||
}
|
||||
function MakeClean {
|
||||
|
||||
function Clean-BuildDir {
|
||||
$Folders = @(
|
||||
"$Build\Mount",
|
||||
"$Build\PEFiles")
|
||||
$Clean = $false
|
||||
"$BuildDir\additions",
|
||||
"$BuildDir\mount",
|
||||
"$BuildDir\pe_files",
|
||||
"$BuildDir\temp")
|
||||
|
||||
# WIM cleanup
|
||||
if (Test-Path "$MountDir") {
|
||||
try {
|
||||
Dismount-WindowsImage -Path "$MountDir" -Discard
|
||||
}
|
||||
catch {
|
||||
# Ignore
|
||||
}
|
||||
Start-Process -FilePath $DISM -ArgumentList @("/Cleanup-Mountpoints") -NoNewWindow -Wait
|
||||
}
|
||||
|
||||
# Folders
|
||||
foreach ($f in $Folders) {
|
||||
if (Test-Path $f) {
|
||||
Write-Host -ForegroundColor "Yellow" ("Found: {0}" -f $f)
|
||||
$Clean = $true
|
||||
}
|
||||
}
|
||||
if (($Clean) -and (Ask-User "Delete the above folder(s)?")) {
|
||||
foreach ($f in $Folders) {
|
||||
if (Test-Path $f) {
|
||||
Remove-Item -Path $f -Recurse -Force
|
||||
}
|
||||
Write-Host -ForegroundColor "Yellow" ("Removing: {0}" -f $f)
|
||||
Remove-Item -Path $f -Recurse -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
function DownloadFile ($Path, $Name, $Url) {
|
||||
$OutFile = "{0}\{1}" -f $Path, $Name
|
||||
|
||||
function Download-File ($Path, $Name, $Url) {
|
||||
$OutFile = "{0}\{1}" -f $Path, $Name
|
||||
Write-Host ("Downloading: $Name")
|
||||
New-Item -Type Directory $Path 2>&1 | Out-Null
|
||||
try {
|
||||
|
|
@ -71,10 +95,128 @@ function DownloadFile ($Path, $Name, $Url) {
|
|||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to download file." ) -ForegroundColor "Red"
|
||||
$global:DownloadErrors += 1
|
||||
Abort
|
||||
}
|
||||
}
|
||||
function FindDynamicUrl ($SourcePage, $RegEx) {
|
||||
|
||||
function Download-SourceFiles {
|
||||
$Sources = Get-Content -Path "$WorkingDir\sources.json" | ConvertFrom-JSON
|
||||
foreach ($s in $Sources) {
|
||||
$Dest = "$BuildDir\downloads\{0}" -f $s.Name
|
||||
if (Test-Path -PathType Leaf -Path "$Dest") {
|
||||
if (Test-Hash -File $Dest -Hash $s.Hash) {
|
||||
continue
|
||||
}
|
||||
# Hash didn't match
|
||||
Remove-Item $Dest -Force
|
||||
}
|
||||
|
||||
# File needs downloaded (again)
|
||||
Download-File -Path "$BuildDir\downloads" -Name $s.Name -Url $s.Url
|
||||
|
||||
# Verify download
|
||||
if ( -Not (Test-Hash -File $Dest -Hash $s.Hash)) {
|
||||
Write-Host (" ERROR: Download failed hash check." ) -ForegroundColor "Red"
|
||||
Abort
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Extract-SourceFiles {
|
||||
$ProgramFilesPE = "$BuildDir\additions\Program Files"
|
||||
New-Item -Type Directory $ProgramFilesPE -Force
|
||||
|
||||
# 7-Zip
|
||||
Write-Host "Extracting: 7-Zip"
|
||||
try {
|
||||
$ArgumentList = @("/a", "$BuildDir\downloads\7z.msi", "TARGETDIR=$TempDir\7zi", "/qn")
|
||||
Start-Process -FilePath "$HostSystem32\msiexec.exe" -ArgumentList $ArgumentList -Wait
|
||||
New-Item -Type Directory "$ProgramFilesPE\7-Zip" 2>&1 | Out-Null
|
||||
Move-Item "$TempDir\7zi\Files\7-Zip\7z.dll" "$ProgramFilesPE\7-Zip\7z.dll"
|
||||
Move-Item "$TempDir\7zi\Files\7-Zip\7z.exe" "$ProgramFilesPE\7-Zip\7z.exe"
|
||||
Move-Item "$TempDir\7zi\Files\7-Zip\License.txt" "$ProgramFilesPE\7-Zip\License.txt"
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
$SevenZip = "$ProgramFilesPE\7-Zip\7z.exe"
|
||||
|
||||
# ConEmu
|
||||
Write-Host "Extracting: ConEmu"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$BuildDir\downloads\ConEmu.7z", "-o`"$ProgramFilesPE`"\ConEmu",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"ConEmu.exe",
|
||||
"ConEmu.map",
|
||||
"ConEmu64.exe",
|
||||
"ConEmu64.map",
|
||||
"ConEmu\CmdInit.cmd",
|
||||
"ConEmu\ConEmuC.exe",
|
||||
"ConEmu\ConEmuC64.exe",
|
||||
"ConEmu\ConEmuCD.dll",
|
||||
"ConEmu\ConEmuCD64.dll",
|
||||
"ConEmu\ConEmuHk.dll",
|
||||
"ConEmu\ConEmuHk64.dll"
|
||||
)
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# Notepad++
|
||||
Write-Host "Extracting: Notepad++"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$BuildDir\downloads\npp.7z", "-o`"$ProgramFilesPE`"\NotepadPlusPlus",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# NTPWEdit
|
||||
Write-Host "Extracting: NTPWEdit"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"e", "$BuildDir\downloads\ntpwedit.zip", "-o`"$ProgramFilesPE`"\NTPWEdit",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"COPYING.txt", "GPL.txt", "ntpwedit64.exe")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Move-Item "$ProgramFilesPE\NTPWEdit\ntpwedit64.exe" "$ProgramFilesPE\NTPWEdit\ntpwedit.exe"
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# OSFMount
|
||||
Write-Host "Extracting: OSFMount"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$BuildDir\downloads\osfmount.7z", "-o`"$ProgramFilesPE`"\OSFMount",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# wimlib
|
||||
Write-Host "Extracting: wimlib"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$BuildDir\downloads\wimlib.zip", "-o`"$ProgramFilesPE`"\wimlib",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
}
|
||||
|
||||
function Find-DynamicUrl ($SourcePage, $RegEx) {
|
||||
# Get source page
|
||||
Invoke-Webrequest -Uri $SourcePage -OutFile "tmp_page"
|
||||
|
||||
|
|
@ -88,11 +230,25 @@ function FindDynamicUrl ($SourcePage, $RegEx) {
|
|||
|
||||
$Url | Select-Object -First 1
|
||||
}
|
||||
|
||||
function Test-Hash ($File, $Hash) {
|
||||
Write-Host -BackgroundColor Black -ForegroundColor Cyan "Verifying ${File}..."
|
||||
$FileHash = (Get-FileHash -Path $File -Algorithm SHA256 -ErrorAction Stop).Hash
|
||||
return ($FileHash.ToLower() -eq $Hash)
|
||||
}
|
||||
|
||||
function WKPause ($Message = "Press Enter to continue... ") {
|
||||
Write-Host $Message -NoNewLine
|
||||
Read-Host
|
||||
}
|
||||
|
||||
## Safety Check ##
|
||||
if ($PSVersionTable.PSVersion.Major -eq 6 -and $PSVersionTable.OS -imatch "Windows 6.1") {
|
||||
Write-Host "`nThis script doesn't support PowerShell 6.0 on Windows 7."
|
||||
Write-Host "Press Enter to exit... " -NoNewLine
|
||||
Abort
|
||||
}
|
||||
|
||||
## PowerShell equivalent of Python's "if __name__ == '__main__'"
|
||||
# Code based on StackOverflow comments
|
||||
# Question: https://stackoverflow.com/q/4693947
|
||||
|
|
@ -100,558 +256,140 @@ function WKPause ($Message = "Press Enter to continue... ") {
|
|||
# Asked by: https://stackoverflow.com/users/65164/mark-mascolino
|
||||
# Answer by: https://stackoverflow.com/users/696808/bacon-bits
|
||||
if ($MyInvocation.InvocationName -ne ".") {
|
||||
Clear-Host
|
||||
Write-Host "Wizard Kit: Windows PE Build Tool`n`n`n`n`n"
|
||||
Push-Location "$WorkingDir"
|
||||
New-Item -Type Directory $BuildDir 2>&1 | Out-Null
|
||||
Clean-BuildDir
|
||||
Copy-Item -Path "$SetupDir\pe\additions" -Destination "$BuildDir\additions" -Recurse -Force
|
||||
|
||||
## Prep ##
|
||||
try {
|
||||
Import-Module -Name $Env:DISMRoot -ErrorAction "stop"
|
||||
}
|
||||
catch {
|
||||
Write-Host -ForegroundColor "Red" "ERROR: Failed to load DISM CmdLet"
|
||||
Abort
|
||||
}
|
||||
Push-Location "$WD"
|
||||
MakeClean
|
||||
New-Item -Type Directory $Build 2>&1 | Out-Null
|
||||
New-Item -Type Directory $LogDir 2>&1 | Out-Null
|
||||
|
||||
## main.py ##
|
||||
if (!(Test-Path "$Build\main.py") -or (Ask-User "Replace existing main.py?")) {
|
||||
Copy-Item -Path "$Bin\Scripts\settings\main.py" -Destination "$Build\main.py" -Force
|
||||
}
|
||||
WKPause "Press Enter to open settings..."
|
||||
Start-Process "$HostSystem32\notepad.exe" -ArgumentList @("$Build\main.py") -Wait
|
||||
$KitNameFull = (Get-Content "$Build\main.py" | Where-Object {$_ -match 'FULL'}) -replace ".*'(.*)'$", '$1'
|
||||
$KitNameShort = (Get-Content "$Build\main.py" | Where-Object {$_ -match 'SHORT'}) -replace ".*'(.*)'$", '$1'
|
||||
|
||||
if (Ask-User "Update Tools?") {
|
||||
$DownloadErrors = 0
|
||||
|
||||
## Download Tools ##
|
||||
$ToolSources = @(
|
||||
# 7-Zip
|
||||
@("7z-installer.msi", "https://www.7-zip.org/a/7z1900.msi"),
|
||||
@("7z-extra.7z", "https://www.7-zip.org/a/7z1900-extra.7z"),
|
||||
# Blue Screen View
|
||||
@("bluescreenview32.zip", "http://www.nirsoft.net/utils/bluescreenview.zip"),
|
||||
@("bluescreenview64.zip", "http://www.nirsoft.net/utils/bluescreenview-x64.zip"),
|
||||
# ConEmu
|
||||
@("ConEmuPack.7z", "https://github.com/Maximus5/ConEmu/releases/download/v19.03.10/ConEmuPack.190310.7z"),
|
||||
# Fast Copy
|
||||
@("fastcopy.zip", "http://ftp.vector.co.jp/71/31/2323/FastCopy363_installer.exe"),
|
||||
# HWiNFO
|
||||
@("hwinfo.zip", "http://files2.majorgeeks.com/377527622c5325acc1cb937fb149d0de922320c0/systeminfo/hwi_602.zip"),
|
||||
# Killer Network Drivers
|
||||
@(
|
||||
"killerinf.zip",
|
||||
("https://www.killernetworking.com"+(FindDynamicUrl "https://www.killernetworking.com/killersupport/category/other-downloads" "Download Killer-Ethernet").replace('&', '&'))
|
||||
),
|
||||
# Notepad++
|
||||
@("npp_x86.7z", "https://notepad-plus-plus.org/repository/7.x/7.6.4/npp.7.6.4.bin.minimalist.7z"),
|
||||
@("npp_amd64.7z", "https://notepad-plus-plus.org/repository/7.x/7.6.4/npp.7.6.4.bin.minimalist.x64.7z"),
|
||||
# NT Password Editor
|
||||
@("ntpwed.zip", "http://cdslow.org.ru/files/ntpwedit/ntpwed07.zip"),
|
||||
# Prime95
|
||||
@("prime95_32.zip", "http://www.mersenne.org/ftp_root/gimps/p95v294b7.win32.zip"),
|
||||
@("prime95_64.zip", "http://www.mersenne.org/ftp_root/gimps/p95v294b8.win64.zip"),
|
||||
# ProduKey
|
||||
@("produkey32.zip", "http://www.nirsoft.net/utils/produkey.zip"),
|
||||
@("produkey64.zip", "http://www.nirsoft.net/utils/produkey-x64.zip"),
|
||||
# Python
|
||||
@("python32.zip", "https://www.python.org/ftp/python/3.7.2/python-3.7.2.post1-embed-win32.zip"),
|
||||
@("python64.zip", "https://www.python.org/ftp/python/3.7.2/python-3.7.2.post1-embed-amd64.zip"),
|
||||
# Python: psutil
|
||||
@(
|
||||
"psutil64.whl",
|
||||
(FindDynamicUrl "https://pypi.org/project/psutil/" "href=.*-cp37-cp37m-win_amd64.whl")
|
||||
),
|
||||
@(
|
||||
"psutil32.whl",
|
||||
(FindDynamicUrl "https://pypi.org/project/psutil/" "href=.*-cp37-cp37m-win32.whl")
|
||||
),
|
||||
# Q-Dir
|
||||
@("qdir32.zip", "https://www.softwareok.com/Download/Q-Dir_Portable.zip"),
|
||||
@("qdir64.zip", "https://www.softwareok.com/Download/Q-Dir_Portable_x64.zip"),
|
||||
# TestDisk / PhotoRec
|
||||
@("testdisk32.zip", "https://www.cgsecurity.org/testdisk-7.1-WIP.win.zip"),
|
||||
@("testdisk64.zip", "https://www.cgsecurity.org/testdisk-7.1-WIP.win64.zip"),
|
||||
# VirtIO drivers
|
||||
@("virtio-win.iso", "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/virtio-win.iso"),
|
||||
# Visual C++ Runtimes
|
||||
@("vcredist_x86.exe", "https://aka.ms/vs/15/release/vc_redist.x86.exe"),
|
||||
@("vcredist_x64.exe", "https://aka.ms/vs/15/release/vc_redist.x64.exe"),
|
||||
# wimlib-imagex
|
||||
@("wimlib32.zip", "https://wimlib.net/downloads/wimlib-1.13.0-windows-i686-bin.zip"),
|
||||
@("wimlib64.zip", "https://wimlib.net/downloads/wimlib-1.13.0-windows-x86_64-bin.zip")
|
||||
)
|
||||
foreach ($Tool in $ToolSources) {
|
||||
DownloadFile -Path $Temp -Name $Tool[0] -Url $Tool[1]
|
||||
}
|
||||
|
||||
## Bail ##
|
||||
# If errors were encountered during downloads
|
||||
if ($DownloadErrors -gt 0) {
|
||||
Abort
|
||||
}
|
||||
|
||||
## Install ##
|
||||
# Visual C++ Runtimes
|
||||
Write-Host "Installing: Visual C++ Runtimes"
|
||||
$ArgumentList = @("/install", "/passive", "/norestart")
|
||||
Start-Process -FilePath "$Temp\vcredist_x86.exe" -ArgumentList $ArgumentList -Wait
|
||||
Start-Process -FilePath "$Temp\vcredist_x64.exe" -ArgumentList $ArgumentList -Wait
|
||||
|
||||
## Extract ##
|
||||
# 7-Zip
|
||||
Write-Host "Extracting: 7-Zip"
|
||||
try {
|
||||
$ArgumentList = @("/a", "$Temp\7z-installer.msi", "TARGETDIR=$Temp\7zi", "/qn")
|
||||
Start-Process -FilePath "$HostSystem32\msiexec.exe" -ArgumentList $ArgumentList -Wait
|
||||
$SevenZip = "$Temp\7zi\Files\7-Zip\7z.exe"
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\7z-extra.7z", "-o$Build\bin\amd64\7-Zip",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"x64\7za.exe", "*.txt")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\7z-extra.7z", "-o$Build\bin\x86\7-Zip",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"7za.exe", "*.txt")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# Blue Screen View
|
||||
Write-Host "Extracting: BlueScreenView"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\bluescreenview64.zip", "-o$Build\bin\amd64\BlueScreenView",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\bluescreenview32.zip", "-o$Build\bin\x86\BlueScreenView",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# ConEmu
|
||||
Write-Host "Extracting: ConEmu"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\ConEmuPack.7z", "-o$Build\bin\amd64\ConEmu",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Remove-Item "$Build\bin\amd64\ConEmu\ConEmu.exe"
|
||||
Remove-Item "$Build\bin\amd64\ConEmu\ConEmu.map"
|
||||
Move-Item "$Build\bin\amd64\ConEmu\ConEmu64.exe" "$Build\bin\amd64\ConEmu\ConEmu.exe" -Force
|
||||
Move-Item "$Build\bin\amd64\ConEmu\ConEmu64.map" "$Build\bin\amd64\ConEmu\ConEmu.map" -Force
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\ConEmuPack.7z", "-o$Build\bin\x86\ConEmu",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Remove-Item "$Build\bin\x86\ConEmu\ConEmu64.exe"
|
||||
Remove-Item "$Build\bin\x86\ConEmu\ConEmu64.map"
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# Fast Copy
|
||||
Write-Host "Extracting: FastCopy"
|
||||
try {
|
||||
# Extract Installer
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\fastcopy.zip", "-o$Temp",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
|
||||
# Extract 64-bit
|
||||
$ArgumentList = @(
|
||||
"/NOSUBDIR", "/DIR=$Build\bin\amd64\FastCopy",
|
||||
"/EXTRACT64")
|
||||
Start-Process -FilePath "$TEMP\FastCopy354_installer.exe" -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Remove-Item "$Build\bin\amd64\FastCopy\setup.exe" -Force
|
||||
|
||||
# Extract 32-bit
|
||||
$ArgumentList = @(
|
||||
"/NOSUBDIR", "/DIR=$Build\bin\x86\FastCopy",
|
||||
"/EXTRACT32")
|
||||
Start-Process -FilePath "$TEMP\FastCopy354_installer.exe" -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Remove-Item "$Build\bin\x86\FastCopy\setup.exe" -Force
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
|
||||
# Killer Network Driver
|
||||
Write-Host "Extracting: Killer Network Driver"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\killerinf.zip", "-o$Build\Drivers\amd64\Killer",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"Production\Windows10-x64\Eth\*")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\killerinf.zip", "-o$Build\Drivers\x86\Killer",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"Production\Windows10-x86\Eth\*")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# HWiNFO
|
||||
Write-Host "Extracting: HWiNFO"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\hwinfo.zip", "-o$Build\bin\amd64\HWiNFO",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0", "HWiNFO64.exe")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\hwinfo.zip", "-o$Build\bin\x86\HWiNFO",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0", "HWiNFO32.exe")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Move-Item "$Build\bin\amd64\HWiNFO\HWiNFO64.exe" "$Build\bin\amd64\HWiNFO\HWiNFO.exe" -Force
|
||||
Move-Item "$Build\bin\x86\HWiNFO\HWiNFO32.exe" "$Build\bin\x86\HWiNFO\HWiNFO.exe" -Force
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# Notepad++
|
||||
Write-Host "Extracting: Notepad++"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\npp_amd64.7z", "-o$Build\bin\amd64\NotepadPlusPlus",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\npp_x86.7z", "-o$Build\bin\x86\NotepadPlusPlus",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Move-Item "$Build\bin\amd64\NotepadPlusPlus\notepad++.exe" "$Build\bin\amd64\NotepadPlusPlus\notepadplusplus.exe" -Force
|
||||
Move-Item "$Build\bin\x86\NotepadPlusPlus\notepad++.exe" "$Build\bin\x86\NotepadPlusPlus\notepadplusplus.exe" -Force
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# NT Password Editor
|
||||
Write-Host "Extracting: NT Password Editor"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\ntpwed.zip", ('-o"{0}\bin\amd64\NT Password Editor"' -f $Build),
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"ntpwedit64.exe", "*.txt")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Move-Item "$Build\bin\amd64\NT Password Editor\ntpwedit64.exe" "$Build\bin\amd64\NT Password Editor\ntpwedit.exe" -Force
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\ntpwed.zip", ('-o"{0}\bin\x86\NT Password Editor"' -f $Build),
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"ntpwedit.exe", "*.txt")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# PhotoRec / TestDisk
|
||||
Write-Host "Extracting: PhotoRec / TestDisk"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\testdisk64.zip", "-o$Build\bin\amd64\TestDisk",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
# Remove destination since Move-Item -Force can't handle this recursive merge
|
||||
Remove-Item "$Build\bin\amd64\TestDisk" -Recurse -Force 2>&1 | Out-Null
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Move-Item "$Build\bin\amd64\TestDisk\testdisk-7.1-WIP\*" "$Build\bin\amd64\TestDisk" -Force
|
||||
Remove-Item "$Build\bin\amd64\TestDisk\testdisk-7.1-WIP" -Recurse -Force
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\testdisk32.zip", "-o$Build\bin\x86\TestDisk",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
# Remove destination since Move-Item -Force can't handle this recursive merge
|
||||
Remove-Item "$Build\bin\x86\TestDisk" -Recurse -Force 2>&1 | Out-Null
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Move-Item "$Build\bin\x86\TestDisk\testdisk-7.1-WIP\*" "$Build\bin\x86\TestDisk" -Force
|
||||
Remove-Item "$Build\bin\x86\TestDisk\testdisk-7.1-WIP" -Recurse -Force
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# Prime95
|
||||
Write-Host "Extracting: Prime95"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\prime95_64.zip", "-o$Build\bin\amd64\Prime95",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\prime95_32.zip", "-o$Build\bin\x86\Prime95",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# ProduKey
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\produkey64.zip", "-o$Build\bin\amd64\ProduKey",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\produkey32.zip", "-o$Build\bin\x86\ProduKey",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# Python (x64)
|
||||
Write-Host "Extracting: Python (x64)"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\python64.zip", "-o$Build\bin\amd64\python",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\psutil64.whl", "-o$Build\bin\amd64\python",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
try {
|
||||
Copy-Item -Path "$HostSystem32\vcruntime140.dll" -Destination "$Build\bin\amd64\python\vcruntime140.dll" -Force
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to copy Visual C++ Runtime DLL." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# Python (x32)
|
||||
Write-Host "Extracting: Python (x32)"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\python32.zip", "-o$Build\bin\x86\python",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\psutil32.whl", "-o$Build\bin\x86\python",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
try {
|
||||
Copy-Item -Path "$HostSysWOW64\vcruntime140.dll" -Destination "$Build\bin\x86\python\vcruntime140.dll" -Force
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to copy Visual C++ Runtime DLL." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# Q-Dir
|
||||
Write-Host "Extracting: Q-Dir"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\qdir64.zip", "-o$Build\bin\amd64",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Move-Item "$Build\bin\amd64\Q-Dir\Q-Dir_x64.exe" "$Build\bin\amd64\Q-Dir\Q-Dir.exe" -Force
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\qdir32.zip", "-o$Build\bin\x86",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# VirtIO Drivers
|
||||
Write-Host "Extracting: VirtIO Drivers"
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\virtio-win.iso", "-o$Build\Drivers\amd64\VirtIO",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"*\w10\amd64\*")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"e", "$Temp\virtio-win.iso", "-o$Build\Drivers\x86\VirtIO",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0",
|
||||
"*\w10\x86\*")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
# wimlib-imagex
|
||||
try {
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\wimlib64.zip", "-o$Build\bin\amd64\wimlib",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @(
|
||||
"x", "$Temp\wimlib32.zip", "-o$Build\bin\x86\wimlib",
|
||||
"-aoa", "-bso0", "-bse0", "-bsp0")
|
||||
Start-Process -FilePath $SevenZip -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
catch {
|
||||
Write-Host (" ERROR: Failed to extract files." ) -ForegroundColor "Red"
|
||||
}
|
||||
|
||||
## Cleanup ##
|
||||
if (Ask-User "Delete temp files?") {
|
||||
Remove-Item "$Temp" -Recurse
|
||||
}
|
||||
}
|
||||
## Download Sources ##
|
||||
Download-SourceFiles
|
||||
Extract-SourceFiles
|
||||
|
||||
## Build ##
|
||||
foreach ($Arch in @("amd64", "x86")) {
|
||||
$Drivers = "$Build\Drivers\$Arch"
|
||||
$Mount = "$Build\Mount"
|
||||
$PEFiles = "$Build\PEFiles\$Arch"
|
||||
|
||||
# Copy WinPE files
|
||||
Write-Host "Copying files..."
|
||||
$Cmd = ("{0}\copype.cmd" -f $Env:WinPERoot)
|
||||
Start-Process -FilePath $Cmd -ArgumentList @($Arch, $PEFiles) -NoNewWindow -Wait
|
||||
# Copy WinPE files
|
||||
Write-Host "Copying files..."
|
||||
$Cmd = ("{0}\copype.cmd" -f $Env:WinPERoot)
|
||||
Start-Process -FilePath $Cmd -ArgumentList @($Arch, $TargetDir) -NoNewWindow -Wait
|
||||
|
||||
# Remove unwanted items
|
||||
foreach ($SubDir in @("media", "media\Boot", "media\EFI\Microsoft\Boot")) {
|
||||
foreach ($Item in Get-ChildItem "$PEFiles\$SubDir") {
|
||||
if ($Item.Name -inotmatch "^(boot|efi|en-us|sources|fonts|resources|bcd|memtest)") {
|
||||
Remove-Item -Path $Item.FullName -Recurse -Force
|
||||
}
|
||||
# Remove unwanted items
|
||||
foreach ($SubDir in @("media", "media\Boot", "media\EFI\Microsoft\Boot")) {
|
||||
foreach ($Item in Get-ChildItem "$TargetDir\$SubDir") {
|
||||
if ($Item.Name -inotmatch "^(boot|efi|en-us|sources|fonts|resources|bcd|memtest)") {
|
||||
Remove-Item -Path $Item.FullName -Recurse -Force
|
||||
}
|
||||
}
|
||||
|
||||
# Mount image
|
||||
Write-Host "Mounting image..."
|
||||
New-Item -Path $Mount -ItemType "directory" -Force | Out-Null
|
||||
Mount-WindowsImage -Path $Mount -ImagePath "$PEFiles\media\sources\boot.wim" -Index 1 -LogPath "$LogDir\DISM.log"
|
||||
|
||||
# Add drivers
|
||||
Add-WindowsDriver -Path $Mount -Driver $Drivers -Recurse -LogPath "$LogDir\DISM.log"
|
||||
|
||||
# Add packages
|
||||
Write-Host "Adding packages:"
|
||||
$WinPEPackages = @(
|
||||
"WinPE-EnhancedStorage",
|
||||
"WinPE-FMAPI",
|
||||
"WinPE-WMI",
|
||||
"WinPE-SecureStartup"
|
||||
)
|
||||
foreach ($Package in $WinPEPackages) {
|
||||
$PackagePath = ("{0}\{1}\WinPE_OCs\{2}.cab" -f $Env:WinPERoot, $Arch, $Package)
|
||||
Write-Host " $Package..."
|
||||
Add-WindowsPackage –PackagePath $PackagePath –Path $Mount -LogPath "$LogDir\DISM.log"
|
||||
$LangPackagePath = ("{0}\{1}\WinPE_OCs\en-us\{2}_en-us.cab" -f $Env:WinPERoot, $Arch, $Package)
|
||||
if (Test-Path $LangPackagePath) {
|
||||
Add-WindowsPackage –PackagePath $LangPackagePath –Path $Mount -LogPath "$LogDir\DISM.log"
|
||||
}
|
||||
}
|
||||
|
||||
# Set RamDisk size
|
||||
$ArgumentList = @(
|
||||
('/Image:"{0}"' -f $Mount),
|
||||
"/Set-ScratchSpace:512",
|
||||
('/LogPath:"{0}\DISM.log"' -f $LogDir)
|
||||
)
|
||||
Start-Process -FilePath $DISM -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
|
||||
# Add tools
|
||||
Write-Host "Copying tools..."
|
||||
Copy-Item -Path "$Build\bin\$Arch" -Destination "$Mount\.bin" -Recurse -Force
|
||||
Copy-Item -Path "$Root\.pe_items\_include\*" -Destination "$Mount\.bin" -Recurse -Force
|
||||
if ($Arch -eq "amd64") {
|
||||
$DestIni = "$Mount\.bin\HWiNFO\HWiNFO64.INI"
|
||||
} else {
|
||||
$DestIni = "$Mount\.bin\HWiNFO\HWiNFO32.INI"
|
||||
}
|
||||
Move-Item -Path "$Mount\.bin\HWiNFO\HWiNFO.INI" -Destination $DestIni -Force
|
||||
Copy-Item -Path "$Root\Images\WinPE.jpg" -Destination "$Mount\.bin\ConEmu\ConEmu.jpg" -Recurse -Force
|
||||
Copy-Item -Path "$Bin\Scripts" -Destination "$Mount\.bin\Scripts" -Recurse -Force
|
||||
Copy-Item -Path "$Build\main.py" -Destination "$Mount\.bin\Scripts\settings\main.py" -Force
|
||||
|
||||
# Add System32 items
|
||||
$HostSystem32 = "{0}\System32" -f $Env:SystemRoot
|
||||
Copy-Item -Path "$Root\.pe_items\System32\*" -Destination "$Mount\Windows\System32" -Recurse -Force
|
||||
$ArgumentList = @("/f", "$Mount\Windows\System32\winpe.jpg", "/a")
|
||||
Start-Process -FilePath "$HostSystem32\takeown.exe" -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @("$Mount\Windows\System32\winpe.jpg", "/grant", "Administrators:F")
|
||||
Start-Process -FilePath "$HostSystem32\icacls.exe" -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Copy-Item -Path "$Root\Images\WinPE.jpg" -Destination "$Mount\Windows\System32\winpe.jpg" -Recurse -Force
|
||||
|
||||
# Load registry hives
|
||||
Write-Host "Updating Registry..."
|
||||
$Reg = "$HostSystem32\reg.exe"
|
||||
$ArgumentList = @("load", "HKLM\WinPE-SW", "$Mount\Windows\System32\config\SOFTWARE")
|
||||
Start-Process -FilePath $Reg -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @("load", "HKLM\WinPE-SYS", "$Mount\Windows\System32\config\SYSTEM")
|
||||
Start-Process -FilePath $Reg -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
|
||||
# Add tools to path
|
||||
## .NET code to properly handle REG_EXPAND_SZ values
|
||||
## Credit: https://www.sepago.com/blog/2013/08/22/reading-and-writing-regexpandsz-data-with-powershell
|
||||
## By: Marius Gawenda
|
||||
$Hive = [Microsoft.Win32.Registry]::LocalMachine
|
||||
$RegPath = "WinPE-SYS\ControlSet001\Control\Session Manager\Environment"
|
||||
$RegKey = $Hive.OpenSubKey($RegPath)
|
||||
$CurValue = $RegKey.GetValue(
|
||||
"Path", $false, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
|
||||
$NewValue = "$CurValue;%SystemDrive%\.bin\7-Zip;%SystemDrive%\.bin\python;%SystemDrive%\.bin\wimlib"
|
||||
Set-ItemProperty -Path "HKLM:\$RegPath" -Name "Path" -Value $NewValue -Force | Out-Null
|
||||
$Hive.close()
|
||||
$RegKey.close()
|
||||
|
||||
# Replace Notepad
|
||||
$RegPath = "HKLM:\WinPE-SW\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe"
|
||||
$NewValue = 'cmd /c "%SystemDrive%\.bin\NotepadPlusPlus\npp.cmd"'
|
||||
New-Item -Path $RegPath -Force | Out-Null
|
||||
New-ItemProperty -Path $RegPath -Name "Debugger" -Value $NewValue -Force | Out-Null
|
||||
|
||||
# Run garbage collection to release potential stale handles
|
||||
## Credit: https://jrich523.wordpress.com/2012/03/06/powershell-loading-and-unloading-registry-hives/
|
||||
Start-Sleep -Seconds 2
|
||||
[gc]::collect()
|
||||
|
||||
# Unload registry hives
|
||||
Start-Sleep -Seconds 2
|
||||
Start-Process -FilePath $Reg -ArgumentList @("unload", "HKLM\WinPE-SW") -NoNewWindow -Wait
|
||||
Start-Process -FilePath $Reg -ArgumentList @("unload", "HKLM\WinPE-SYS") -NoNewWindow -Wait
|
||||
|
||||
# Unmount image
|
||||
Write-Host "Dismounting image..."
|
||||
Dismount-WindowsImage -Path $Mount -Save -LogPath "$LogDir\DISM.log"
|
||||
|
||||
# Create ISO
|
||||
New-Item -Type Directory "$Root\OUT_PE" 2>&1 | Out-Null
|
||||
$ArgumentList = @("/iso", $PEFiles, "$Root\OUT_PE\$KitNameShort-WinPE-$Date-$Arch.iso")
|
||||
$Cmd = "{0}\MakeWinPEMedia.cmd" -f $Env:WinPERoot
|
||||
Start-Process -FilePath $Cmd -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
}
|
||||
|
||||
# Mount image
|
||||
Write-Host "Mounting image..."
|
||||
New-Item -Path $MountDir -ItemType "directory" -Force | Out-Null
|
||||
Mount-WindowsImage -Path $MountDir -ImagePath "$TargetDir\media\sources\boot.wim" -Index 1
|
||||
|
||||
# Add drivers
|
||||
Write-Host "Adding drivers..."
|
||||
Add-WindowsDriver -Path $MountDir -Driver "$SetupDir\pe\drivers" -ForceUnsigned -Recurse
|
||||
|
||||
# Add packages
|
||||
Write-Host "Adding packages..."
|
||||
$WinPEPackages = @(
|
||||
"WinPE-EnhancedStorage",
|
||||
"WinPE-FMAPI",
|
||||
"WinPE-WMI",
|
||||
"WinPE-SecureStartup"
|
||||
)
|
||||
foreach ($Package in $WinPEPackages) {
|
||||
$PackagePath = ("{0}\{1}\WinPE_OCs\{2}.cab" -f $Env:WinPERoot, $Arch, $Package)
|
||||
Write-Host " $Package..."
|
||||
Add-WindowsPackage –PackagePath $PackagePath –Path $MountDir
|
||||
$LangPackagePath = ("{0}\{1}\WinPE_OCs\en-us\{2}_en-us.cab" -f $Env:WinPERoot, $Arch, $Package)
|
||||
if (Test-Path $LangPackagePath) {
|
||||
Add-WindowsPackage –PackagePath $LangPackagePath –Path $MountDir
|
||||
}
|
||||
}
|
||||
|
||||
# Set RamDisk size
|
||||
$ArgumentList = @(
|
||||
('/Image:"{0}"' -f $MountDir),
|
||||
"/Set-ScratchSpace:512"
|
||||
)
|
||||
Start-Process -FilePath $DISM -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
|
||||
# Add tools
|
||||
Write-Host "Copying tools..."
|
||||
Copy-Item -Path "$BuildDir\additions\*" -Destination $MountDir -Recurse -Force
|
||||
Copy-Item -Path "$RootDir\Images\WinPE.jpg" -Destination "$MountDir\Program Files\ConEmu\ConEmu.jpg" -Recurse -Force
|
||||
|
||||
# Add System32 items
|
||||
$ArgumentList = @("/f", "$MountDir\Windows\System32\winpe.jpg", "/a")
|
||||
Start-Process -FilePath "$HostSystem32\takeown.exe" -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @("$MountDir\Windows\System32\winpe.jpg", "/grant", "Administrators:F")
|
||||
Start-Process -FilePath "$HostSystem32\icacls.exe" -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
Copy-Item -Path "$RootDir\Images\WinPE.jpg" -Destination "$MountDir\Windows\System32\winpe.jpg" -Force
|
||||
|
||||
# Load registry hives
|
||||
Write-Host "Updating Registry..."
|
||||
$Reg = "$HostSystem32\reg.exe"
|
||||
$ArgumentList = @("load", "HKLM\WinPE-SW", "$MountDir\Windows\System32\config\SOFTWARE")
|
||||
Start-Process -FilePath $Reg -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
$ArgumentList = @("load", "HKLM\WinPE-SYS", "$MountDir\Windows\System32\config\SYSTEM")
|
||||
Start-Process -FilePath $Reg -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
|
||||
# Configure CMD (command aliases "DOSKEY Macros" and tab completion)
|
||||
$RegPath = "HKLM:\WinPE-SW\Microsoft\Command Processor"
|
||||
$NewValue = "doskey /macrofile=X:\Windows\System32\custom.doskey"
|
||||
New-Item -Path $RegPath -Force | Out-Null
|
||||
New-ItemProperty -Path $RegPath -Name "AutoRun" -Value $NewValue -Force | Out-Null
|
||||
New-ItemProperty -Path $RegPath -Name "CompletionChar" -Value 9 -Type DWord -Force | Out-Null
|
||||
New-ItemProperty -Path $RegPath -Name "PathCompletionChar" -Value 9 -Type DWord -Force | Out-Null
|
||||
|
||||
# Add tools to path
|
||||
## .NET code to properly handle REG_EXPAND_SZ values
|
||||
## Credit: https://www.sepago.com/blog/2013/08/22/reading-and-writing-regexpandsz-data-with-powershell
|
||||
## By: Marius Gawenda
|
||||
$Hive = [Microsoft.Win32.Registry]::LocalMachine
|
||||
$RegPath = "WinPE-SYS\ControlSet001\Control\Session Manager\Environment"
|
||||
$RegKey = $Hive.OpenSubKey($RegPath)
|
||||
$CurValue = $RegKey.GetValue(
|
||||
"Path", $false, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
|
||||
$NewValue = "$CurValue;%ProgramFiles%\7-Zip;%ProgramFiles%\OSFMount;%ProgramFiles%\wimlib"
|
||||
Set-ItemProperty -Path "HKLM:\$RegPath" -Name "Path" -Value $NewValue -Force | Out-Null
|
||||
$Hive.close()
|
||||
$RegKey.close()
|
||||
|
||||
# Run garbage collection to release potential stale handles
|
||||
## Credit: https://jrich523.wordpress.com/2012/03/06/powershell-loading-and-unloading-registry-hives/
|
||||
Start-Sleep -Seconds 2
|
||||
[gc]::collect()
|
||||
|
||||
# Unload registry hives
|
||||
Start-Sleep -Seconds 2
|
||||
Start-Process -FilePath $Reg -ArgumentList @("unload", "HKLM\WinPE-SW") -NoNewWindow -Wait
|
||||
Start-Process -FilePath $Reg -ArgumentList @("unload", "HKLM\WinPE-SYS") -NoNewWindow -Wait
|
||||
|
||||
# Unmount image
|
||||
Write-Host "Dismounting image..."
|
||||
Dismount-WindowsImage -Path $MountDir -Save
|
||||
|
||||
# Rebuild image
|
||||
Write-Host "Recompressing image..."
|
||||
Move-Item "$TargetDir\media\sources\boot.wim" "$TargetDir\media\sources\boot-edited.wim"
|
||||
Export-WindowsImage -DestinationImagePath "$TargetDir\media\sources\boot.wim" -SourceImagePath "$TargetDir\media\sources\boot-edited.wim" -SourceIndex 1 -CompressionType Max
|
||||
Remove-Item "$TargetDir\media\sources\boot-edited.wim" -Force
|
||||
|
||||
# Create ISO
|
||||
New-Item -Type Directory "$SetupDir\OUT_PE" 2>&1 | Out-Null
|
||||
$ArgumentList = @("/iso", $TargetDir, "$SetupDir\OUT_PE\$KitNameShort-WinPE-$Date-$Arch.iso", "/f")
|
||||
$Cmd = "{0}\MakeWinPEMedia.cmd" -f $Env:WinPERoot
|
||||
Start-Process -FilePath $Cmd -ArgumentList $ArgumentList -NoNewWindow -Wait
|
||||
|
||||
## Cleanup ##
|
||||
Remove-Item -Path "$Build\Mount" -Recurse -Force
|
||||
Remove-Item -Path "$Build\PEFiles" -Recurse -Force
|
||||
Remove-Item -Path "$MountDir" -Recurse -Force
|
||||
|
||||
## Done ##
|
||||
Pop-Location
|
||||
Write-Host "`nDone."
|
||||
WKPause "Press Enter to exit... "
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue