Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def audit(directory):
payload = stream.read(row['bytes'])
assert len(payload) == row['bytes'] and hashlib.sha256(payload).hexdigest() == row['sha256']
components[row['name']] = payload
profile = Path(orchard_hardware.__file__).parent / 'boot/initramfs/j71b/recovery/boot.json'
profile = Path(orchard_hardware.__file__).parent / 'boot/initramfs/recovery/boot.json'
assert components['bootargs'] == json.loads(profile.read_text())['bootargs'].encode(), 'Recovery must preserve the tested standard boot profile'
recovery = newc(gzip.decompress(components['initramfs']))
for name in ('usr/lib/firmware/regulatory.db', 'usr/lib/firmware/regulatory.db.p7s'):
Expand All @@ -107,8 +107,7 @@ def audit(directory):
for name, (data, mode, link) in entries.items():
if data is not None and (name.startswith(('usr/libexec/orchard-j71b/', 'usr/lib/modules/',
'usr/lib/firmware/', 'usr/share/licenses/orchard-regdb/')) or
name in ('usr/bin/orchard-device', 'usr/libexec/j71b-check-platform',
'usr/libexec/j71b-charge-lease', 'etc/orchard/public.SHA256SUMS')):
name in ('usr/bin/orchard-device', 'etc/orchard/public.SHA256SUMS')):
assert recovery[name][0] == data and stat.S_IMODE(recovery[name][1]) == mode
shared += 1
for data, mode in recovery.values():
Expand Down
8 changes: 4 additions & 4 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def root_archive(base, base_receipt, components, output, version):
for name, target in (('start-ssh', 'usr/sbin/recovery-start-ssh'),
('authorize-key', 'usr/sbin/authorize-key'),
('capture-adt', 'usr/sbin/capture-adt')):
additions[target] = ((hardware / 'boot/initramfs/j71b/recovery' / name).read_bytes(), 0o755)
additions['etc/udhcpd.conf'] = ((hardware / 'boot/initramfs/j71b/recovery/udhcpd.conf').read_bytes(), 0o644)
additions[target] = ((hardware / 'boot/initramfs/recovery' / name).read_bytes(), 0o755)
additions['etc/udhcpd.conf'] = ((hardware / 'boot/initramfs/recovery/udhcpd.conf').read_bytes(), 0o644)
additions.update({
'etc/orchard/release.json': (json.dumps({'protocol': 1, 'release': version, 'profile': 'j71b',
'kernel_release': kernel_release}).encode(), 0o644),
Expand Down Expand Up @@ -132,7 +132,7 @@ def parents(name):
member.mode, member.size = mode, len(data)
add(member, data)
for service in ('orchard-session', 'orchard-platform', 'orchard-diagnostics',
'orchard-charge', 'orchard-dhcp', 'orchard-buttons', 'orchard-ready'):
'orchard-dhcp', 'orchard-buttons', 'orchard-ready'):
name = 'etc/runlevels/default/' + service
parents(name)
member = tarfile.TarInfo(name)
Expand All @@ -155,7 +155,7 @@ def parents(name):
def manifests(output, version, root):
document = ('schema = 1\nkind = "orchard.install"\ndistro = "minimal-linux"\n'
'name = "Minimal Alpine"\nversion = ' + json.dumps(version) + '\n'
'device = "j71b"\nboot_method = "checkm8-pongo"\nmin_orchard = "0.1.10"\nprotocol = 1\n'
'device = "j71b"\nboot_method = "checkm8-pongo"\nmin_orchard = "0.1.11"\nprotocol = 1\n'
'\n[install]\ndefault_root = "/minimal"\n')
for role, name in (('root', 'rootfs.tar.gz'), ('boot', 'recovery.bin'), ('pongo', 'pongo.bin')):
p = output / name
Expand Down
2 changes: 1 addition & 1 deletion cli
Submodule cli updated 45 files
+3 −2 NOTICE
+5 −5 pyproject.toml
+90 −0 src/orchard_cli/apple/device.py
+2 −1 src/orchard_cli/apple/ipsw.py
+83 −0 src/orchard_cli/apple/kernelcache.py
+0 −0 src/orchard_cli/apple/smartio.py
+396 −0 src/orchard_cli/apple/z2fw.py
+24 −36 src/orchard_cli/build.py
+5 −4 src/orchard_cli/command.py
+10 −2 src/orchard_cli/contracts.py
+29 −21 src/orchard_cli/devices.py
+87 −0 src/orchard_cli/firmware.py
+0 −1 src/orchard_cli/j71b/__init__.py
+0 −78 src/orchard_cli/j71b/adapter.py
+0 −11 src/orchard_cli/j71b/config.py
+0 −53 src/orchard_cli/j71b/inputs.py
+0 −19 src/orchard_cli/j71b/mixin.py
+0 −90 src/orchard_cli/j71b/prepare.py
+0 −234 src/orchard_cli/j71b/touch.py
+29 −9 src/orchard_cli/kernel.py
+2 −5 src/orchard_cli/launch.py
+5 −0 src/orchard_cli/manifests.py
+3 −1 src/orchard_cli/ram.py
+178 −0 src/orchard_cli/recipe.py
+31 −3 src/orchard_cli/releases.py
+26 −5 src/orchard_cli/service.py
+0 −83 src/orchard_cli/staging.py
+53 −0 tests/hardware_layout.py
+41 −45 tests/test_adapter_contract.py
+12 −8 tests/test_binary_codecs.py
+9 −6 tests/test_build_config.py
+47 −19 tests/test_host_workflow.py
+7 −5 tests/test_kernel_sdk.py
+3 −3 tests/test_launch.py
+40 −0 tests/test_launcher_selection.py
+1 −1 tests/test_manifests.py
+9 −7 tests/test_package_boundaries.py
+3 −1 tests/test_ram.py
+81 −0 tests/test_recipe.py
+4 −2 tests/test_runtime.py
+27 −59 tests/test_shared_build_cache.py
+6 −8 tests/test_sources.py
+0 −42 tests/test_staging.py
+257 −0 tests/test_z2fw.py
+4 −2 tests/typecheck_adapter.py
2 changes: 1 addition & 1 deletion hardware
5 changes: 2 additions & 3 deletions image/j71b/image_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def stop_diagnostics():
CONFIG = Path('/etc/orchard/release.json')
INSTALLED = Path('/.orchard-install.json')
STARTED = Path('/run/openrc/started')
SERVICES = ('orchard-platform', 'orchard-diagnostics', 'orchard-charge', 'orchard-dhcp', 'orchard-buttons')
SERVICES = ('orchard-platform', 'orchard-diagnostics', 'orchard-dhcp', 'orchard-buttons')


def process(pid, executable):
Expand All @@ -39,7 +39,6 @@ def ready(*, ssh_revoked=False):
if not (ssh_revoked and name == 'orchard-diagnostics')) and
process(1, '/usr/bin/busybox') and
(ssh_revoked or process(record['diagnostics_pid'], DIAGNOSTICS_EXECUTABLE)) and
process(record['charge_pid'], '/usr/bin/busybox') and
process(record['dhcp_pid'], '/usr/libexec/minimal-linux/busybox') and
process(record['buttons_pid'], str(Path('/usr/bin/python3').resolve())) and
json.loads(INSTALLED.read_text())['release'] == record['release'])
Expand All @@ -55,7 +54,7 @@ def validate_handoff(root):
raise ValueError('Alpine PID 1 must be BusyBox init')
for name in ('usr/bin/busybox', 'usr/bin/python3', 'usr/sbin/openrc',
'usr/sbin/openrc-run', 'usr/sbin/dropbear',
'usr/libexec/j71b-check-platform', 'usr/libexec/j71b-charge-lease',
'usr/libexec/minimal-check-platform',
'usr/libexec/minimal-ready', 'usr/libexec/minimal-clear-splash',
'usr/libexec/minimal-console', 'usr/libexec/minimal-buttons',
'usr/libexec/minimal-screen-toggle', 'usr/libexec/minimal-brightness-display',
Expand Down
6 changes: 0 additions & 6 deletions system/overlay/etc/init.d/orchard-charge

This file was deleted.

4 changes: 2 additions & 2 deletions system/overlay/etc/init.d/orchard-platform
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/sbin/openrc-run
description="Verify preserved J71b hardware state and installed payload"
description="Verify the hardware and the installed hardware files"
depend() { need orchard-session; }
start() {
ebegin "Checking Orchard hardware"
/usr/libexec/j71b-check-platform >/run/orchard-platform.log 2>&1
/usr/libexec/minimal-check-platform >/run/orchard-platform.log 2>&1
eend $?
}
2 changes: 1 addition & 1 deletion system/overlay/etc/init.d/orchard-ready
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/sbin/openrc-run
description="Publish headless readiness only after required OpenRC services"
depend() { need orchard-platform orchard-diagnostics orchard-charge orchard-dhcp orchard-buttons; }
depend() { need orchard-platform orchard-diagnostics orchard-dhcp orchard-buttons; }
start() {
ebegin "Checking minimal Linux readiness"
/usr/libexec/minimal-ready
Expand Down
15 changes: 15 additions & 0 deletions system/overlay/usr/libexec/minimal-check-platform
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh
# Ready only on the hardware this system was installed for. No bring-up gates:
# the installed kernel and device, and the installed hardware files. Wi-Fi,
# Bluetooth and touch are reported, not required: experimental boards may
# lack some of them.
set -eu
config=/etc/orchard/release.json
field() { python3 -c 'import json, sys; print(json.load(open(sys.argv[1]))[sys.argv[2]])' "$config" "$1"; }
[ "$(uname -r)" = "$(field kernel_release)" ]
[ "$(tr '\000' '\n' < /proc/device-tree/compatible | head -1)" = "apple,$(field profile)" ]
state() { if eval "$2"; then echo "$1: ready"; else echo "$1: missing"; fi; }
state wifi '[ -d /sys/class/net/wlan0 ]'
state bluetooth '[ -d /sys/class/bluetooth/hci0 ]'
state touch 'grep -q "^N: Name=\".*Touchscreen\"" /proc/bus/input/devices'
sha256sum -c /usr/share/ipadlinux/hardware.SHA256SUMS >/dev/null
1 change: 0 additions & 1 deletion system/overlay/usr/libexec/minimal-ready
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ while True:
record = {'boot_id': policy.BOOT_ID.read_text().strip(),
'release': json.loads(policy.CONFIG.read_text())['release'],
'diagnostics_pid': int(Path('/run/recovery/dropbear.pid').read_text()),
'charge_pid': int(Path('/run/orchard-charge.pid').read_text()),
'dhcp_pid': int(Path('/run/orchard-dhcp.pid').read_text()),
'buttons_pid': int(Path('/run/orchard-buttons.pid').read_text())}
temporary = policy.RECORD.with_suffix('.pending')
Expand Down
2 changes: 1 addition & 1 deletion tests/native-image.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

# Exercise the actual platform checker's checksum command with Alpine's tools,
# without bypassing its real hardware preconditions in the shipped checker.
checksum = Path('/usr/libexec/j71b-check-platform').read_text().splitlines()[-1]
checksum = Path('/usr/libexec/minimal-check-platform').read_text().splitlines()[-1]
assert checksum == 'sha256sum -c /usr/share/ipadlinux/hardware.SHA256SUMS >/dev/null'
Path('/tmp/checksum-data').write_bytes(b'known data')
Path('/tmp/checksums').write_text(hashlib.sha256(b'known data').hexdigest() + ' /tmp/checksum-data\n')
Expand Down
3 changes: 1 addition & 2 deletions tests/native-init.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,10 @@
from pathlib import Path
assert str(Path('/proc/1/exe').readlink()) == '/usr/bin/busybox'
assert Path('/proc/1/cmdline').read_bytes().split(b'\0')[0] in (b'/sbin/init', b'init')
assert subprocess.run(['/usr/libexec/j71b-check-platform'], capture_output=True).returncode != 0
assert subprocess.run(['/usr/libexec/minimal-check-platform'], capture_output=True).returncode != 0
status=json.loads(subprocess.check_output(['/usr/bin/orchard-device','status']))['result']
assert status['ready'] is False
assert not Path('/run/minimal-linux-ready.json').exists()
assert not Path('/run/openrc/started/orchard-charge').exists()
assert not Path('/run/openrc/started/orchard-ready').exists()
print(json.dumps({'busybox_pid1':True,'openrc_booted':True,'diagnostics_started':True,
'dhcp_started':True,'dhcp_process_alive_and_udp67_bound':True,'hardware_gate_failed_as_expected':True,'ready':False,
Expand Down
8 changes: 4 additions & 4 deletions tests/test_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def setUp(self):
for service in policy.SERVICES:
(policy.STARTED / service).touch()
self.record = {'release': 'test', 'boot_id': 'current-boot',
'diagnostics_pid': 2, 'charge_pid': 3, 'dhcp_pid': 4, 'buttons_pid': 5}
'diagnostics_pid': 2, 'dhcp_pid': 4, 'buttons_pid': 5}
self.save()
# Tests run on macOS as an unprivileged developer. Root metadata and
# live Linux executables are checked separately in the native image.
Expand All @@ -44,14 +44,14 @@ def save(self):

def test_current_boot_with_all_services_is_ready(self):
self.assertTrue(policy.ready())
self.assertEqual(self.process.call_count, 5)
self.assertEqual(self.process.call_count, 4)

def test_revoked_ssh_does_not_remove_hardware_readiness(self):
(policy.STARTED / 'orchard-diagnostics').unlink()
self.process.side_effect = lambda pid, exe: pid != 2
self.assertFalse(policy.ready())
self.assertTrue(policy.ready(ssh_revoked=True))
(policy.STARTED / 'orchard-charge').unlink()
(policy.STARTED / 'orchard-dhcp').unlink()
self.assertFalse(policy.ready(ssh_revoked=True))

def test_prior_boot_is_not_ready(self):
Expand All @@ -69,7 +69,7 @@ def test_different_installed_root_is_not_ready(self):
self.assertFalse(policy.ready())

def test_missing_service_is_not_ready(self):
(policy.STARTED / 'orchard-charge').unlink()
(policy.STARTED / 'orchard-dhcp').unlink()
self.assertFalse(policy.ready())

def test_dead_or_different_process_is_not_ready(self):
Expand Down
34 changes: 17 additions & 17 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading