tan-cli 0.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tan/__init__.py +0 -0
- tan/__main__.py +120 -0
- tan/cli.py +939 -0
- tan/command_table.py +265 -0
- tan/commands/__init__.py +8 -0
- tan/commands/bootstrap_cmd.py +4856 -0
- tan/commands/bootstrap_patches.py +164 -0
- tan/commands/bootstrap_toolchain_fetch.py +155 -0
- tan/commands/bootstrap_toolchain_pin.py +36 -0
- tan/commands/build/__init__.py +1 -0
- tan/commands/build/configure_inputs.py +277 -0
- tan/commands/build/execute.py +1852 -0
- tan/commands/build/host_python.py +59 -0
- tan/commands/build/link_stale.py +78 -0
- tan/commands/build/manifest.py +428 -0
- tan/commands/build/materialise.py +81 -0
- tan/commands/build/token_substitution.py +381 -0
- tan/commands/build/toolchain.py +482 -0
- tan/commands/build/user_defines_wipe.py +115 -0
- tan/commands/build/workspace_patches.py +65 -0
- tan/commands/build_cmd.py +2236 -0
- tan/commands/build_output.py +331 -0
- tan/commands/clean_cmd.py +1183 -0
- tan/commands/completion_cmd.py +786 -0
- tan/commands/debug_config_cmd.py +2425 -0
- tan/commands/diff_cmd.py +940 -0
- tan/commands/doctor_cmd.py +4767 -0
- tan/commands/examples_cmd.py +644 -0
- tan/commands/explain_cmd.py +1319 -0
- tan/commands/faultdecode_cmd.py +931 -0
- tan/commands/flash_atoc_guard.py +240 -0
- tan/commands/flash_cmd.py +5731 -0
- tan/commands/flash_mram_guard.py +150 -0
- tan/commands/flash_ram.py +578 -0
- tan/commands/flash_raw.py +583 -0
- tan/commands/generate_cmd.py +1456 -0
- tan/commands/image_cmd.py +753 -0
- tan/commands/init_cmd.py +1740 -0
- tan/commands/inspect_cmd.py +377 -0
- tan/commands/kconfig_cmd.py +734 -0
- tan/commands/model_cmd.py +1514 -0
- tan/commands/model_device_cmd.py +351 -0
- tan/commands/model_device_live.py +234 -0
- tan/commands/model_host_cmd.py +430 -0
- tan/commands/model_zoo_cmd.py +363 -0
- tan/commands/monitor_actions.py +125 -0
- tan/commands/monitor_cmd.py +626 -0
- tan/commands/monitor_session.py +505 -0
- tan/commands/new_som_cmd.py +1522 -0
- tan/commands/pinmux_cmd.py +568 -0
- tan/commands/presets_cmd.py +1123 -0
- tan/commands/probe_cmd.py +421 -0
- tan/commands/reset_cmd.py +354 -0
- tan/commands/reset_confirm.py +168 -0
- tan/commands/run_cmd.py +637 -0
- tan/commands/scaffold_cmd.py +490 -0
- tan/commands/sdk_cmd.py +1723 -0
- tan/commands/size_cmd.py +1020 -0
- tan/commands/support_bundle_cmd.py +1073 -0
- tan/commands/trace_cmd.py +341 -0
- tan/commands/validate_cmd.py +2009 -0
- tan/commands/west_forward_cmd.py +736 -0
- tan/commands/workspace_patch_check.py +296 -0
- tan/core/__init__.py +1 -0
- tan/core/alp_conf_pregen.py +100 -0
- tan/core/artifact_provenance.py +240 -0
- tan/core/atoc_guard.py +276 -0
- tan/core/atoc_guard_messages.py +232 -0
- tan/core/atoc_replacement.py +118 -0
- tan/core/atomic_write.py +178 -0
- tan/core/board_context.py +351 -0
- tan/core/board_diagnostic.py +111 -0
- tan/core/board_files.py +221 -0
- tan/core/board_validator.py +542 -0
- tan/core/board_validator_compat.py +196 -0
- tan/core/board_validator_run.py +129 -0
- tan/core/board_validator_schema.py +186 -0
- tan/core/board_validator_skew.py +46 -0
- tan/core/board_yaml_edit.py +295 -0
- tan/core/board_yaml_pos.py +118 -0
- tan/core/bootstrap.py +2572 -0
- tan/core/build_plan.py +625 -0
- tan/core/consent.py +104 -0
- tan/core/console_filter.py +245 -0
- tan/core/debug_launch.py +1803 -0
- tan/core/devicetree_lint.py +168 -0
- tan/core/dir_removal.py +229 -0
- tan/core/doctor_git.py +172 -0
- tan/core/doctor_libraries.py +253 -0
- tan/core/doctor_render.py +185 -0
- tan/core/doctor_scope.py +66 -0
- tan/core/doctor_setools.py +237 -0
- tan/core/doctor_stale.py +180 -0
- tan/core/document_guards.py +723 -0
- tan/core/dp_id.py +97 -0
- tan/core/elf_load.py +63 -0
- tan/core/error_catalog.py +171 -0
- tan/core/example_catalog.py +499 -0
- tan/core/example_facets.py +151 -0
- tan/core/faultdecode.py +521 -0
- tan/core/flash_plan.py +2501 -0
- tan/core/flow_d_report.py +381 -0
- tan/core/flow_d_uptime.py +164 -0
- tan/core/fs_confine.py +130 -0
- tan/core/global_flags.py +230 -0
- tan/core/host_python.py +210 -0
- tan/core/image_bundle.py +247 -0
- tan/core/inert.py +147 -0
- tan/core/jlink_binary.py +128 -0
- tan/core/jlink_probe.py +481 -0
- tan/core/jsonc_splice.py +404 -0
- tan/core/launch_provenance.py +257 -0
- tan/core/link_refusal.py +76 -0
- tan/core/metadata_schema.py +376 -0
- tan/core/model_check.py +227 -0
- tan/core/model_device.py +449 -0
- tan/core/model_doctor.py +198 -0
- tan/core/model_host.py +48 -0
- tan/core/model_list.py +112 -0
- tan/core/model_zoo.py +353 -0
- tan/core/module_template.py +340 -0
- tan/core/mram_link.py +87 -0
- tan/core/new_som_ospi.py +94 -0
- tan/core/os_class.py +159 -0
- tan/core/patch_paths.py +87 -0
- tan/core/pending.py +40 -0
- tan/core/plain_zephyr_plan.py +138 -0
- tan/core/plan_exec.py +373 -0
- tan/core/plan_tokens.py +600 -0
- tan/core/probe.py +155 -0
- tan/core/probe_plan.py +237 -0
- tan/core/proxy.py +168 -0
- tan/core/publish.py +31 -0
- tan/core/python_floor.py +178 -0
- tan/core/ram_run.py +694 -0
- tan/core/ram_watch.py +231 -0
- tan/core/raw_write.py +160 -0
- tan/core/reset_plan.py +56 -0
- tan/core/run.py +161 -0
- tan/core/scaffold.py +2203 -0
- tan/core/scaffold_selftest_identity.py +225 -0
- tan/core/sdk_default_registry.py +565 -0
- tan/core/sdk_discovery.py +996 -0
- tan/core/sdk_removal.py +465 -0
- tan/core/serial_actions.py +175 -0
- tan/core/serial_capture.py +185 -0
- tan/core/serial_url.py +45 -0
- tan/core/setools.py +608 -0
- tan/core/setools_scratch.py +243 -0
- tan/core/shapes.py +194 -0
- tan/core/size.py +610 -0
- tan/core/som_buildability.py +204 -0
- tan/core/som_schema_version.py +62 -0
- tan/core/subprocess_env.py +201 -0
- tan/core/sysbuild_image.py +94 -0
- tan/core/system_manifest.py +827 -0
- tan/core/text_layout.py +73 -0
- tan/core/timestamp.py +182 -0
- tan/core/tool_lookup.py +383 -0
- tan/core/toolchain_pin.py +117 -0
- tan/core/toolchain_provision.py +1224 -0
- tan/core/trusted_path.py +134 -0
- tan/core/uboot_breakin.py +154 -0
- tan/core/uri_reference.py +415 -0
- tan/core/user_defines.py +152 -0
- tan/core/venv.py +332 -0
- tan/core/west_patches.py +143 -0
- tan/core/west_workspace_refusal.py +159 -0
- tan/core/zephyr_env.py +124 -0
- tan/env.py +185 -0
- tan/envelope.py +647 -0
- tan/exit_codes.py +12 -0
- tan/lazy_typer.py +185 -0
- tan/model/__init__.py +2 -0
- tan/model/_gen_fixture.py +132 -0
- tan/model/adapters/__init__.py +116 -0
- tan/model/adapters/cpu.py +26 -0
- tan/model/adapters/deepx.py +94 -0
- tan/model/adapters/drpai.py +242 -0
- tan/model/adapters/ethos_u.py +951 -0
- tan/model/adapters/executorch.py +55 -0
- tan/model/analyze.py +694 -0
- tan/model/build.py +304 -0
- tan/model/check.py +682 -0
- tan/model/manifest.py +625 -0
- tan/model/measure.py +216 -0
- tan/model/npu_ops_validate.py +130 -0
- tan/model/package.py +125 -0
- tan/model/perf.py +635 -0
- tan/model/perf_apply.py +721 -0
- tan/model/prep.py +193 -0
- tan/model/sram_fit.py +502 -0
- tan/model/targets.py +374 -0
- tan/model/tensorio.py +287 -0
- tan/net.py +73 -0
- tan/output_format.py +213 -0
- tan/planner/__init__.py +219 -0
- tan/planner/aperture.py +202 -0
- tan/planner/buildplan.py +1092 -0
- tan/planner/camera_owner.py +192 -0
- tan/planner/cameras.py +132 -0
- tan/planner/carveout.py +755 -0
- tan/planner/cli.py +274 -0
- tan/planner/headers.py +315 -0
- tan/planner/kconfig.py +2435 -0
- tan/planner/kconfig_symbols.py +473 -0
- tan/planner/libraries.py +677 -0
- tan/planner/link_target.py +237 -0
- tan/planner/linux_ownership.py +216 -0
- tan/planner/loader.py +1525 -0
- tan/planner/manifest.py +116 -0
- tan/planner/memory.py +161 -0
- tan/planner/memregion.py +56 -0
- tan/planner/models.py +533 -0
- tan/planner/orchestrator.py +874 -0
- tan/planner/ownership.py +203 -0
- tan/planner/partition.py +1160 -0
- tan/planner/paths.py +32 -0
- tan/planner/plain_slice.py +139 -0
- tan/planner/project_emit/__init__.py +60 -0
- tan/planner/project_emit/bom_netlist.py +375 -0
- tan/planner/project_emit/dts.py +580 -0
- tan/planner/project_emit/hw_info.py +221 -0
- tan/planner/project_emit/native_sim.py +136 -0
- tan/planner/project_emit/west_libs.py +213 -0
- tan/planner/project_loader.py +264 -0
- tan/planner/sdk_capability.py +203 -0
- tan/planner/sdk_compat.py +395 -0
- tan/planner/secure.py +350 -0
- tan/planner/slugs.py +394 -0
- tan/planner/som_metadata.py +325 -0
- tan/planner/strict_loaders.py +131 -0
- tan/planner/template.py +1037 -0
- tan/planner/template_pins.py +535 -0
- tan/planner/template_rewrite.py +714 -0
- tan/planner/topology.py +208 -0
- tan/planner/validate.py +365 -0
- tan/planner/whole_device_alias.py +67 -0
- tan/planner/zephyr_board.py +3510 -0
- tan/planner_cli.py +97 -0
- tan/planner_emit.py +617 -0
- tan/planner_root.py +119 -0
- tan/soc_ref.py +58 -0
- tan/templates/__init__.py +34 -0
- tan/templates/vendored/MANIFEST.md +1862 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/README.md +112 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/board.yaml +38 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.conf +11 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.overlay +29 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/prj.conf +5 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/src/main.c +266 -0
- tan/templates/vendored/diagnostics/E1M-AEN801/testcase.yaml +53 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/README.md +112 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/board.yaml +38 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.conf +11 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.overlay +29 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/prj.conf +5 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/src/main.c +266 -0
- tan/templates/vendored/diagnostics/E1M-V2N101/testcase.yaml +53 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/CMakeLists.txt +10 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/README.md +75 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/board.yaml +38 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/prj.conf +8 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.c +371 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.h +178 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/src/main.c +373 -0
- tan/templates/vendored/edge-ai/E1M-AEN801/testcase.yaml +62 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/CMakeLists.txt +10 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/README.md +75 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/board.yaml +37 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/prj.conf +8 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.c +371 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.h +178 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/src/main.c +373 -0
- tan/templates/vendored/edge-ai/E1M-V2N101/testcase.yaml +62 -0
- tan/templates/vendored/iot/E1M-AEN801/CMakeLists.txt +14 -0
- tan/templates/vendored/iot/E1M-AEN801/README.md +103 -0
- tan/templates/vendored/iot/E1M-AEN801/board.yaml +69 -0
- tan/templates/vendored/iot/E1M-AEN801/prj.conf +15 -0
- tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.c +196 -0
- tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.h +173 -0
- tan/templates/vendored/iot/E1M-AEN801/src/main.c +262 -0
- tan/templates/vendored/iot/E1M-AEN801/testcase.yaml +68 -0
- tan/templates/vendored/minimal/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/minimal/E1M-AEN801/README.md +108 -0
- tan/templates/vendored/minimal/E1M-AEN801/board.yaml +32 -0
- tan/templates/vendored/minimal/E1M-AEN801/prj.conf +8 -0
- tan/templates/vendored/minimal/E1M-AEN801/src/main.c +111 -0
- tan/templates/vendored/minimal/E1M-AEN801/testcase.yaml +49 -0
- tan/templates/vendored/minimal/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/minimal/E1M-V2N101/README.md +108 -0
- tan/templates/vendored/minimal/E1M-V2N101/board.yaml +32 -0
- tan/templates/vendored/minimal/E1M-V2N101/prj.conf +8 -0
- tan/templates/vendored/minimal/E1M-V2N101/src/main.c +111 -0
- tan/templates/vendored/minimal/E1M-V2N101/testcase.yaml +49 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/README.md +120 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/board.yaml +57 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/boards/native_sim_native_64.overlay +40 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/CMakeLists.txt +13 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/main.c +171 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/prj.conf +17 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/testcase.yaml +23 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/prj.conf +22 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/src/main.c +185 -0
- tan/templates/vendored/multicore-mailbox/E1M-AEN801/testcase.yaml +26 -0
- tan/templates/vendored/sensor/E1M-AEN801/CMakeLists.txt +8 -0
- tan/templates/vendored/sensor/E1M-AEN801/README.md +112 -0
- tan/templates/vendored/sensor/E1M-AEN801/board.yaml +57 -0
- tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.conf +10 -0
- tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.overlay +28 -0
- tan/templates/vendored/sensor/E1M-AEN801/prj.conf +5 -0
- tan/templates/vendored/sensor/E1M-AEN801/src/main.c +186 -0
- tan/templates/vendored/sensor/E1M-AEN801/testcase.yaml +52 -0
- tan/templates/vendored/sensor/E1M-V2N101/CMakeLists.txt +8 -0
- tan/templates/vendored/sensor/E1M-V2N101/README.md +112 -0
- tan/templates/vendored/sensor/E1M-V2N101/board.yaml +57 -0
- tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.conf +10 -0
- tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.overlay +28 -0
- tan/templates/vendored/sensor/E1M-V2N101/prj.conf +5 -0
- tan/templates/vendored/sensor/E1M-V2N101/src/main.c +186 -0
- tan/templates/vendored/sensor/E1M-V2N101/testcase.yaml +52 -0
- tan/version.py +102 -0
- tan_cli-0.7.0.dist-info/METADATA +125 -0
- tan_cli-0.7.0.dist-info/RECORD +330 -0
- tan_cli-0.7.0.dist-info/WHEEL +5 -0
- tan_cli-0.7.0.dist-info/entry_points.txt +2 -0
- tan_cli-0.7.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""The IO half of Flow A's whole-ATOC guard (tan-cli#1267): the file reads
|
|
3
|
+
and the one unlink `tan flash` needs around a `west flash` spawn. Every
|
|
4
|
+
decision lives in `tan.core.atoc_guard` and every sentence in
|
|
5
|
+
`tan.core.atoc_guard_messages`; this module only fetches their inputs.
|
|
6
|
+
|
|
7
|
+
What is read, none of it tan's own, all from the build west will flash:
|
|
8
|
+
|
|
9
|
+
* a sysbuild's top-level `domains.yaml`, for the one domain whose
|
|
10
|
+
`build_dir` the runner actually runs in (and writes its verdict under). A
|
|
11
|
+
multi-domain sysbuild is refused by the runner itself before its guard
|
|
12
|
+
runs (alp-sdk#2274), so tan says so instead of guessing a domain;
|
|
13
|
+
* that build's `zephyr/runners.yaml`, for the runner `west flash` falls back
|
|
14
|
+
to when the manifest names none;
|
|
15
|
+
* that build's `zephyr_modules.txt`, for the alp-sdk module checkout the
|
|
16
|
+
build used -- the one `west flash` imports `alif_flash` from, which need
|
|
17
|
+
not be the SDK tan is bound to. The bound SDK is the fallback only when
|
|
18
|
+
the build has no readable module list, and every message names the file;
|
|
19
|
+
* that module's `scripts/west_commands/runners/alif_flash.py`, for whether
|
|
20
|
+
the runner has the guard (`runner_has_guard`: the `--replace-atoc`
|
|
21
|
+
argument AND the v1 verdict schema);
|
|
22
|
+
* the runner's verdict, `<domain build dir>/alif_flash/atoc-guard.json`.
|
|
23
|
+
|
|
24
|
+
The verdict is removed BEFORE the spawn. The runner does the same itself at
|
|
25
|
+
the top of `do_run`, so that "no file" means "the guard never reached a
|
|
26
|
+
verdict for this attempt" (alp-sdk docs/aen-provisioning.md section 0.6). But
|
|
27
|
+
`do_run` is only reached once west has parsed its arguments and loaded the
|
|
28
|
+
runner; a `west flash` that fails before that leaves the LAST run's verdict
|
|
29
|
+
in place, and reading it would report an old `clear` (or an old refusal) as
|
|
30
|
+
this attempt's result. Removing it first closes that gap without trusting
|
|
31
|
+
timestamps.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
import os
|
|
37
|
+
from collections.abc import Mapping
|
|
38
|
+
from typing import Any, Callable, Iterable
|
|
39
|
+
|
|
40
|
+
from tan.core.atoc_guard import (
|
|
41
|
+
ALIF_FLASH_RUNNER,
|
|
42
|
+
RUNNER_SOURCE_PARTS,
|
|
43
|
+
VERDICT_DIR,
|
|
44
|
+
VERDICT_FILE,
|
|
45
|
+
GuardVerdict,
|
|
46
|
+
ReplaceAtocDecision,
|
|
47
|
+
RunnerFacts,
|
|
48
|
+
decide_replace_atoc,
|
|
49
|
+
parse_domain_build_dirs,
|
|
50
|
+
parse_flash_runner,
|
|
51
|
+
parse_module_dir,
|
|
52
|
+
parse_verdict,
|
|
53
|
+
runner_has_guard,
|
|
54
|
+
)
|
|
55
|
+
from tan.core.atoc_guard_messages import (
|
|
56
|
+
no_verdict_after_success,
|
|
57
|
+
passed_note,
|
|
58
|
+
refusal_message,
|
|
59
|
+
unreadable_note,
|
|
60
|
+
)
|
|
61
|
+
from tan.core.flash_plan import fa_str, zephyr_west_build_dir
|
|
62
|
+
|
|
63
|
+
WEST_FLASH = "zephyr_west_flash"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _read_text(path: str) -> str | None:
|
|
67
|
+
"""`None` for a missing, unreadable or non-UTF-8 file -- every input here
|
|
68
|
+
is best-effort, and the pure layer turns `None` into "could not tell"."""
|
|
69
|
+
try:
|
|
70
|
+
with open(path, encoding="utf-8") as handle:
|
|
71
|
+
return handle.read()
|
|
72
|
+
except (OSError, UnicodeDecodeError):
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def absolutise_build_dir(flash_args: Any, base: str) -> Any:
|
|
77
|
+
"""`flash_args` with a relative `build_dir` anchored on `base` -- the cwd
|
|
78
|
+
`west flash` is spawned in (the west topdir, else tan's own cwd). West
|
|
79
|
+
resolves `--build-dir` against ITS cwd, so tan must read the guard files
|
|
80
|
+
under the same directory, and passes the same absolute path on the argv
|
|
81
|
+
so the two can never name different trees. A new mapping; the manifest's
|
|
82
|
+
own is not touched. Anything else is returned unchanged."""
|
|
83
|
+
if not isinstance(flash_args, Mapping):
|
|
84
|
+
return flash_args
|
|
85
|
+
build_dir = fa_str(flash_args, "build_dir")
|
|
86
|
+
if build_dir is None or os.path.isabs(build_dir):
|
|
87
|
+
return flash_args
|
|
88
|
+
return {**flash_args, "build_dir": os.path.join(base, build_dir)}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _image_dir(build_dir: str) -> tuple[str | None, str | None]:
|
|
92
|
+
"""`(the build dir the runner runs in, None)`, or `(None, why not)`."""
|
|
93
|
+
domains_path = os.path.join(build_dir, "domains.yaml")
|
|
94
|
+
text = _read_text(domains_path)
|
|
95
|
+
if text is None:
|
|
96
|
+
return build_dir, None
|
|
97
|
+
dirs = parse_domain_build_dirs(text)
|
|
98
|
+
if dirs is None:
|
|
99
|
+
return None, f"{build_dir} is a sysbuild tree whose {domains_path} could not be read"
|
|
100
|
+
if len(dirs) > 1:
|
|
101
|
+
return None, (
|
|
102
|
+
f"{build_dir} is a sysbuild tree with {len(dirs)} domains ({domains_path}); "
|
|
103
|
+
"the alif_flash runner refuses a multi-domain sysbuild before its guard runs "
|
|
104
|
+
"and leaves no verdict (alp-sdk#2274)"
|
|
105
|
+
)
|
|
106
|
+
only = dirs[0]
|
|
107
|
+
return (only if os.path.isabs(only) else os.path.join(build_dir, only)), None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _runner_source(image_dir: str, sdk_root: str) -> tuple[str, str]:
|
|
111
|
+
"""`(the alif_flash.py to check, where that path came from)`."""
|
|
112
|
+
modules_path = os.path.join(image_dir, "zephyr_modules.txt")
|
|
113
|
+
modules = _read_text(modules_path)
|
|
114
|
+
if modules is None:
|
|
115
|
+
return (
|
|
116
|
+
os.path.join(sdk_root, *RUNNER_SOURCE_PARTS),
|
|
117
|
+
f"the bound alp-sdk; the build has no readable {modules_path}",
|
|
118
|
+
)
|
|
119
|
+
module_dir = parse_module_dir(modules)
|
|
120
|
+
if module_dir is None:
|
|
121
|
+
return modules_path, "that build lists no alp-sdk module, so its runner is not checkable"
|
|
122
|
+
return (
|
|
123
|
+
os.path.join(module_dir, *RUNNER_SOURCE_PARTS),
|
|
124
|
+
f"the alp-sdk module this build used, per {modules_path}",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def runner_facts(flash_args: Any, build_dir: str, sdk_root: str) -> RunnerFacts:
|
|
129
|
+
"""Everything `decide_replace_atoc` needs about one west entry."""
|
|
130
|
+
image_dir, why_not = _image_dir(build_dir)
|
|
131
|
+
if image_dir is None:
|
|
132
|
+
return RunnerFacts(unknown_reason=why_not, verdict_dir=build_dir)
|
|
133
|
+
runner = fa_str(flash_args, "runner")
|
|
134
|
+
runners_path = os.path.join(image_dir, "zephyr", "runners.yaml")
|
|
135
|
+
if runner is None:
|
|
136
|
+
text = _read_text(runners_path)
|
|
137
|
+
runner = parse_flash_runner(text) if text is not None else None
|
|
138
|
+
if runner != ALIF_FLASH_RUNNER:
|
|
139
|
+
reason = (
|
|
140
|
+
f"flash_args.runner is unset and {runners_path} is missing or names no "
|
|
141
|
+
"flash-runner. Build first, or set flash_args.runner"
|
|
142
|
+
)
|
|
143
|
+
return RunnerFacts(runner=runner, unknown_reason=reason, verdict_dir=image_dir)
|
|
144
|
+
source, origin = _runner_source(image_dir, sdk_root)
|
|
145
|
+
text = _read_text(source) if source.endswith(".py") else None
|
|
146
|
+
return RunnerFacts(
|
|
147
|
+
runner=runner, source=source, origin=origin,
|
|
148
|
+
has_guard=text is not None and runner_has_guard(text), verdict_dir=image_dir,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def plan_atoc_guard(
|
|
153
|
+
method: str, entry_id: str, flash_args: Any, artefact_path: str, sdk_root: str,
|
|
154
|
+
replace_atoc: bool,
|
|
155
|
+
) -> tuple[ReplaceAtocDecision, str]:
|
|
156
|
+
"""The guard decision for one entry, plus the dir its verdict lands under
|
|
157
|
+
(`""` for a non-west entry). `flash_args` must already be absolutised."""
|
|
158
|
+
if method != WEST_FLASH:
|
|
159
|
+
return decide_replace_atoc(method, entry_id, RunnerFacts(), replace_atoc), ""
|
|
160
|
+
facts = runner_facts(flash_args, zephyr_west_build_dir(flash_args, artefact_path), sdk_root)
|
|
161
|
+
return decide_replace_atoc(method, entry_id, facts, replace_atoc), facts.verdict_dir
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def entries_taking_the_flag(
|
|
165
|
+
candidates: Iterable[tuple[str, str, Any, str]], sdk_root: str
|
|
166
|
+
) -> list[str]:
|
|
167
|
+
"""The ids of every `(method, entry_id, flash_args, artefact_path)` that
|
|
168
|
+
`--replace-atoc` would actually be appended to."""
|
|
169
|
+
return [
|
|
170
|
+
entry_id
|
|
171
|
+
for method, entry_id, flash_args, artefact_path in candidates
|
|
172
|
+
if plan_atoc_guard(method, entry_id, flash_args, artefact_path, sdk_root, True)[0].append
|
|
173
|
+
]
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def verdict_path(verdict_dir: str) -> str:
|
|
177
|
+
return os.path.join(verdict_dir, VERDICT_DIR, VERDICT_FILE)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def clear_stale_verdict(verdict_dir: str, remove: Callable[[str], None] = os.remove) -> str | None:
|
|
181
|
+
"""Remove a previous attempt's verdict before spawning (see the module
|
|
182
|
+
docstring). Returns why it could not be removed, else `None`; the caller
|
|
183
|
+
then distrusts whatever file is there afterwards."""
|
|
184
|
+
path = verdict_path(verdict_dir)
|
|
185
|
+
try:
|
|
186
|
+
remove(path)
|
|
187
|
+
except FileNotFoundError:
|
|
188
|
+
return None
|
|
189
|
+
except OSError as err:
|
|
190
|
+
return f"a verdict left by an earlier run at {path} could not be removed first ({err})"
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def read_verdict(verdict_dir: str) -> GuardVerdict | str:
|
|
195
|
+
"""This attempt's verdict, or why there is none to use."""
|
|
196
|
+
path = verdict_path(verdict_dir)
|
|
197
|
+
if not os.path.exists(path):
|
|
198
|
+
return (
|
|
199
|
+
f"no {path} was written for this attempt -- the runner stopped before its "
|
|
200
|
+
"guard ran, or is not one that writes a verdict"
|
|
201
|
+
)
|
|
202
|
+
text = _read_text(path)
|
|
203
|
+
if text is None:
|
|
204
|
+
return f"{path} could not be read"
|
|
205
|
+
result = parse_verdict(text)
|
|
206
|
+
return result if isinstance(result, GuardVerdict) else f"{path}: {result}"
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def guarded_failure_message(
|
|
210
|
+
west_message: str, entry_id: str, verdict_dir: str, stale: str | None,
|
|
211
|
+
earlier: Mapping[str, str], *, refused_west_message: str | None = None,
|
|
212
|
+
) -> tuple[str, bool]:
|
|
213
|
+
"""The message for a failed `west flash` on a guarded runner, and whether
|
|
214
|
+
the guard refused it. `earlier`: ATOC section -> the entry of this run
|
|
215
|
+
that wrote it. `refused_west_message`, when given, stands in for
|
|
216
|
+
`west_message` on a refusal only (tan-cli#1426: west's tail without its
|
|
217
|
+
runner-loading warnings)."""
|
|
218
|
+
verdict = stale if stale is not None else read_verdict(verdict_dir)
|
|
219
|
+
if isinstance(verdict, str):
|
|
220
|
+
return west_message + unreadable_note(verdict), False
|
|
221
|
+
if verdict.refused:
|
|
222
|
+
reported = west_message if refused_west_message is None else refused_west_message
|
|
223
|
+
return f"{refusal_message(entry_id, verdict, earlier)} West reported: {reported}", True
|
|
224
|
+
return f"{west_message} ({passed_note(verdict, failed=True)}; the failure came after it)", False
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def guarded_success(
|
|
228
|
+
ok_message: str, entry_id: str, verdict_dir: str, stale: str | None, source: str
|
|
229
|
+
) -> tuple[str, str | None, tuple[str, ...]]:
|
|
230
|
+
"""`(message, unguarded warning or None, ATOC sections this write put
|
|
231
|
+
there)` for a `west flash` that succeeded on a guarded runner. No usable
|
|
232
|
+
verdict means the guard did not run for this write -- never silence."""
|
|
233
|
+
if stale is not None:
|
|
234
|
+
return ok_message + unreadable_note(stale), None, ()
|
|
235
|
+
verdict = read_verdict(verdict_dir)
|
|
236
|
+
if isinstance(verdict, GuardVerdict) and verdict.refused:
|
|
237
|
+
verdict = f"it says {verdict.status!r}, yet west flash succeeded"
|
|
238
|
+
if isinstance(verdict, str):
|
|
239
|
+
return ok_message, no_verdict_after_success(entry_id, verdict, source), ()
|
|
240
|
+
return f"{ok_message}; {passed_note(verdict)}", None, verdict.allowed
|