"""Offline image-policy negative controls; actual boot acceptance is recorded separately."""
import copy
import json
from pathlib import Path
import subprocess
import struct
import tempfile
import unittest
import zlib
from ReadImage import verify_single_edition
ROOT = Path(__file__).resolve().parents[2]
class SingleEditionImageTests(unittest.TestCase):
def fixture(self, edition='Desktop'):
paths = sorted(['EFI/BOOT/BOOTX64.EFI', 'EFI/XFE/Limine.efi', 'System/Kernel.elf', 'System/BootShim.json', 'Limine.conf'])
manifest = {'Edition': edition, 'DeploymentPolicy': 'SingleEditionOnly', 'ImageBytes': 134217728,
'BootEntries': [edition], 'DefaultBootEntry': edition, 'BootMenuTimeoutSeconds': 0,
'Resolution': '1280x800', 'IndependentKernelBuild': {'Edition': edition}}
config = ('timeout: 0\nserial: yes\nverbose: no\nterse: yes\nquiet: yes\nfirmware_logo: no\n\n'
f'/XFESystem {edition}\n protocol: limine\n resolution: 1280x800x32\n path: boot():/System/Kernel.elf\n')
return {'FilePaths': paths}, {'Limine.conf': config.encode()}, manifest
def test_each_edition_has_one_kernel_and_no_selection_menu(self):
for edition in ('Console', 'Desktop'):
with self.subTest(edition=edition):
result = verify_single_edition(*self.fixture(edition))
self.assertEqual(edition, result['Edition'])
self.assertFalse(result['SystemSelectionMenu'])
def usb_fixture(self, edition='Desktop'):
inspection, files, manifest = self.fixture(edition)
inspection['FilePaths'] = sorted(inspection['FilePaths'] + ['Workspace.bin', 'UserFiles/UsbHello.dll'])
inspection['FileFirstLbas'] = {'Workspace.bin': 4096}
manifest.update(UsbWorkspace=True, ImageBytes=268435456, WorkspaceBytes=67108864, WorkspaceFirstLba=4096)
workspace = bytearray(67108864)
struct.pack_into('<QIII', workspace, 0, 0x5357425355454658, 1, 131072, 65535)
struct.pack_into('<I', workspace, 20, zlib.crc32(workspace[:20]))
files['Workspace.bin'] = workspace
return inspection, files, manifest
def test_usb_workspace_keeps_exactly_one_edition(self):
for edition in ('Console', 'Desktop'):
proof = verify_single_edition(*self.usb_fixture(edition))
self.assertTrue(proof['UsbWorkspace'])
self.assertEqual(proof['KernelCount'], 1)
self.assertFalse(proof['SystemSelectionMenu'])
def test_usb_workspace_checksum_extent_and_size_are_required(self):
for change in ('crc', 'extent', 'size'):
inspection, files, manifest = self.usb_fixture()
if change == 'crc': files['Workspace.bin'][20] ^= 1
elif change == 'extent': manifest['WorkspaceFirstLba'] += 1
else: manifest['WorkspaceBytes'] -= 512
with self.subTest(change=change), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
def test_dual_or_mislabeled_kernel_is_rejected(self):
for edition in ('Dual', 'Unknown'):
inspection, files, manifest = self.fixture(); manifest['Edition'] = edition
with self.subTest(edition=edition), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
inspection, files, manifest = self.fixture(); manifest['IndependentKernelBuild']['Edition'] = 'Console'
with self.assertRaises(AssertionError): verify_single_edition(inspection, files, manifest)
def test_multiple_boot_entries_are_rejected(self):
inspection, files, manifest = self.fixture(); manifest['BootEntries'].append('Console')
with self.assertRaises(AssertionError): verify_single_edition(inspection, files, manifest)
def test_second_kernel_in_manifest_is_rejected(self):
for key in ('ConsoleKernelPath', 'ConsoleKernelSha256', 'IndependentConsoleKernelBuild'):
inspection, files, manifest = self.fixture(); manifest[key] = 'second kernel'
with self.subTest(key=key), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
def test_hidden_second_kernel_in_actual_fat_inventory_is_rejected(self):
inspection, files, manifest = self.fixture(); inspection['FilePaths'].append('System/Console.elf')
with self.assertRaises(AssertionError): verify_single_edition(inspection, files, manifest)
def test_menu_and_kernel_path_changes_are_rejected(self):
_, baseline, _ = self.fixture()
for config in (baseline['Limine.conf'] + b'\n/XFESystem Console\n',
baseline['Limine.conf'].replace(b'quiet: yes', b'quiet: no'),
baseline['Limine.conf'].replace(b'System/Kernel.elf', b'System/Console.elf')):
inspection, files, manifest = self.fixture(); files['Limine.conf'] = config
with self.subTest(config=config), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
def test_timeout_and_old_dual_size_are_rejected(self):
for changes in ({'BootMenuTimeoutSeconds': 10}, {'ImageBytes': 268435456}, {'DeploymentPolicy': 'Dual'}):
inspection, files, manifest = self.fixture(); manifest.update(changes)
with self.subTest(changes=changes), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
def test_old_combined_image_cli_cannot_write_output(self):
with tempfile.TemporaryDirectory() as folder:
output = Path(folder)/'System.img'
result = subprocess.run(['dotnet', str(ROOT/'Tools/CSharpBoot/bin/Release/net10.0/PackImage.dll'),
'Desktop.elf', str(output), '1280x800', '--independent-kernel', '--console-kernel', 'Console.elf'],
capture_output=True, text=True)
self.assertNotEqual(0, result.returncode)
self.assertIn('dual-system images are no longer generated', result.stderr)
self.assertFalse(output.exists())
def test_old_dual_media_profile_is_rejected_before_disk_access(self):
for write in (False, True):
with self.subTest(write=write), tempfile.TemporaryDirectory() as folder:
log = Path(folder)/'Rejected.json'
result = subprocess.run(['powershell.exe', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass',
'-File', str(ROOT/'scripts/physical-media.ps1'), '-ImageProfile', 'IndependentDualCSharp256',
'-ResultPath', str(log), *(['-Write'] if write else [])], capture_output=True)
self.assertNotEqual(0, result.returncode)
receipt = json.loads(log.read_text(encoding='utf-8-sig'))
self.assertFalse(receipt['PhysicalDiskOpened'])
self.assertTrue(receipt['HandlesClosed'])
self.assertEqual('failed', receipt['Status'])
self.assertIn('Dual-system deployment was retired', receipt['Error'])
if __name__ == '__main__':
unittest.main()
"""Offline image-policy negative controls; actual boot acceptance is recorded separately."""
import copy
import json
from pathlib import Path
import subprocess
import struct
import tempfile
import unittest
import zlib
from ReadImage import verify_single_edition
ROOT = Path(__file__).resolve().parents[2]
class SingleEditionImageTests(unittest.TestCase):
def fixture(self, edition='Desktop'):
paths = sorted(['EFI/BOOT/BOOTX64.EFI', 'EFI/XFE/Limine.efi', 'System/Kernel.elf', 'System/BootShim.json', 'Limine.conf'])
manifest = {'Edition': edition, 'DeploymentPolicy': 'SingleEditionOnly', 'ImageBytes': 134217728,
'BootEntries': [edition], 'DefaultBootEntry': edition, 'BootMenuTimeoutSeconds': 0,
'Resolution': '1280x800', 'IndependentKernelBuild': {'Edition': edition}}
config = ('timeout: 0\nserial: yes\nverbose: no\nterse: yes\nquiet: yes\nfirmware_logo: no\n\n'
f'/XFESystem {edition}\n protocol: limine\n resolution: 1280x800x32\n path: boot():/System/Kernel.elf\n')
return {'FilePaths': paths}, {'Limine.conf': config.encode()}, manifest
def test_each_edition_has_one_kernel_and_no_selection_menu(self):
for edition in ('Console', 'Desktop'):
with self.subTest(edition=edition):
result = verify_single_edition(*self.fixture(edition))
self.assertEqual(edition, result['Edition'])
self.assertFalse(result['SystemSelectionMenu'])
def usb_fixture(self, edition='Desktop'):
inspection, files, manifest = self.fixture(edition)
inspection['FilePaths'] = sorted(inspection['FilePaths'] + ['Workspace.bin', 'UserFiles/UsbHello.dll'])
inspection['FileFirstLbas'] = {'Workspace.bin': 4096}
manifest.update(UsbWorkspace=True, ImageBytes=268435456, WorkspaceBytes=67108864, WorkspaceFirstLba=4096)
workspace = bytearray(67108864)
struct.pack_into('<QIII', workspace, 0, 0x5357425355454658, 1, 131072, 65535)
struct.pack_into('<I', workspace, 20, zlib.crc32(workspace[:20]))
files['Workspace.bin'] = workspace
return inspection, files, manifest
def test_usb_workspace_keeps_exactly_one_edition(self):
for edition in ('Console', 'Desktop'):
proof = verify_single_edition(*self.usb_fixture(edition))
self.assertTrue(proof['UsbWorkspace'])
self.assertEqual(proof['KernelCount'], 1)
self.assertFalse(proof['SystemSelectionMenu'])
def test_usb_workspace_checksum_extent_and_size_are_required(self):
for change in ('crc', 'extent', 'size'):
inspection, files, manifest = self.usb_fixture()
if change == 'crc': files['Workspace.bin'][20] ^= 1
elif change == 'extent': manifest['WorkspaceFirstLba'] += 1
else: manifest['WorkspaceBytes'] -= 512
with self.subTest(change=change), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
def test_dual_or_mislabeled_kernel_is_rejected(self):
for edition in ('Dual', 'Unknown'):
inspection, files, manifest = self.fixture(); manifest['Edition'] = edition
with self.subTest(edition=edition), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
inspection, files, manifest = self.fixture(); manifest['IndependentKernelBuild']['Edition'] = 'Console'
with self.assertRaises(AssertionError): verify_single_edition(inspection, files, manifest)
def test_multiple_boot_entries_are_rejected(self):
inspection, files, manifest = self.fixture(); manifest['BootEntries'].append('Console')
with self.assertRaises(AssertionError): verify_single_edition(inspection, files, manifest)
def test_second_kernel_in_manifest_is_rejected(self):
for key in ('ConsoleKernelPath', 'ConsoleKernelSha256', 'IndependentConsoleKernelBuild'):
inspection, files, manifest = self.fixture(); manifest[key] = 'second kernel'
with self.subTest(key=key), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
def test_hidden_second_kernel_in_actual_fat_inventory_is_rejected(self):
inspection, files, manifest = self.fixture(); inspection['FilePaths'].append('System/Console.elf')
with self.assertRaises(AssertionError): verify_single_edition(inspection, files, manifest)
def test_menu_and_kernel_path_changes_are_rejected(self):
_, baseline, _ = self.fixture()
for config in (baseline['Limine.conf'] + b'\n/XFESystem Console\n',
baseline['Limine.conf'].replace(b'quiet: yes', b'quiet: no'),
baseline['Limine.conf'].replace(b'System/Kernel.elf', b'System/Console.elf')):
inspection, files, manifest = self.fixture(); files['Limine.conf'] = config
with self.subTest(config=config), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
def test_timeout_and_old_dual_size_are_rejected(self):
for changes in ({'BootMenuTimeoutSeconds': 10}, {'ImageBytes': 268435456}, {'DeploymentPolicy': 'Dual'}):
inspection, files, manifest = self.fixture(); manifest.update(changes)
with self.subTest(changes=changes), self.assertRaises(AssertionError):
verify_single_edition(inspection, files, manifest)
def test_old_combined_image_cli_cannot_write_output(self):
with tempfile.TemporaryDirectory() as folder:
output = Path(folder)/'System.img'
result = subprocess.run(['dotnet', str(ROOT/'Tools/CSharpBoot/bin/Release/net10.0/PackImage.dll'),
'Desktop.elf', str(output), '1280x800', '--independent-kernel', '--console-kernel', 'Console.elf'],
capture_output=True, text=True)
self.assertNotEqual(0, result.returncode)
self.assertIn('dual-system images are no longer generated', result.stderr)
self.assertFalse(output.exists())
def test_old_dual_media_profile_is_rejected_before_disk_access(self):
for write in (False, True):
with self.subTest(write=write), tempfile.TemporaryDirectory() as folder:
log = Path(folder)/'Rejected.json'
result = subprocess.run(['powershell.exe', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass',
'-File', str(ROOT/'scripts/physical-media.ps1'), '-ImageProfile', 'IndependentDualCSharp256',
'-ResultPath', str(log), *(['-Write'] if write else [])], capture_output=True)
self.assertNotEqual(0, result.returncode)
receipt = json.loads(log.read_text(encoding='utf-8-sig'))
self.assertFalse(receipt['PhysicalDiskOpened'])
self.assertTrue(receipt['HandlesClosed'])
self.assertEqual('failed', receipt['Status'])
self.assertIn('Dual-system deployment was retired', receipt['Error'])
if __name__ == '__main__':
unittest.main()