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
2 changes: 1 addition & 1 deletion skills.json
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@
"homepage": "https://github.com/qualcomm-linux/qcom-linux-skills",
"versions": [
{
"version": "0.1",
"version": "0.2",
"path": "skills/qcom-boot-validate",
"docPath": "skills/qcom-boot-validate/SKILL.md",
"files": ["skills/qcom-boot-validate/**"],
Expand Down
8 changes: 6 additions & 2 deletions skills/qcom-boot-validate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ description: >-
over ssh). Do NOT use for flashing (see qcom-flash-qdl) or for
diagnosing a healthy-but-degraded system.
metadata:
version: "0.1"
version: "0.2"
---

# Validate a board boots over the serial console
Expand Down Expand Up @@ -59,7 +59,11 @@ ssh <host> "python3 - --port /dev/ttyUSB0 --password oelinux123" \
after) resetting, e.g. right after a flash completes.
- `--power-cycle-cmd` runs a host command once at startup for setups that
can drive board power programmatically (lab automation, smart PDU). Keep
site-specific automation in that command, not in this skill.
site-specific automation in that command, not in this skill. The command
is split shell-style and run without a shell; wrap it in `sh -c '...'`
if it needs pipes, redirection, variable or `~` expansion, or is a script
without a `#!` line. If it cannot be started, the script warns and keeps
watching the console, so the board must then be reset by hand.
- Exit code `0` on `BOOT-VALIDATION: PASS`, non-zero on failure. The full
console capture is mirrored to the log file (default
`/tmp/qcom-boot-validate-<timestamp>.log`) for evidence.
Expand Down
29 changes: 21 additions & 8 deletions skills/qcom-boot-validate/scripts/boot-validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
By default the script only watches the console: start it, then power-cycle
or reset the board (or start it right after flashing). Alternatively pass
--power-cycle-cmd with a host command that power-cycles the board (e.g. a
lab automation wrapper); it is run once at startup.
lab automation wrapper); it is run once at startup, without a shell (wrap it
in sh -c '...' for shell syntax).

Prints "BOOT-VALIDATION: PASS ..." and exits 0 on success; prints
"BOOT-VALIDATION: FAIL ..." and exits non-zero otherwise. The full console
Expand All @@ -26,6 +27,7 @@
import argparse
import os
import re
import shlex
import subprocess
import sys
import time
Expand Down Expand Up @@ -77,7 +79,8 @@ def main():
ap.add_argument("--timeout", type=float, default=300.0,
help="seconds to wait for the login prompt")
ap.add_argument("--power-cycle-cmd", default=None,
help="optional host command that power-cycles the board; run once at startup")
help="optional host command that power-cycles the board; run once at "
"startup, without a shell (use sh -c '...' for shell syntax)")
ap.add_argument("--logfile", default=None,
help="console capture path (default: /tmp/qcom-boot-validate-<ts>.log)")
args = ap.parse_args()
Expand Down Expand Up @@ -183,12 +186,22 @@ def wait_for_text(needle, timeout):
# 1) trigger a clean boot -------------------------------------------------
if args.power_cycle_cmd:
log("power-cycling board via: %s" % args.power_cycle_cmd)
r = subprocess.run(args.power_cycle_cmd, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
log("power-cycle rc=%d: %s" % (r.returncode,
r.stdout.decode(errors="replace").strip()))
if r.returncode != 0:
log("WARNING: power-cycle command returned non-zero; continuing to watch console")
# No shell: the command is split into argv; wrap it in sh -c '...'
# explicitly if it needs shell syntax (pipes, redirection, $VAR, ~)
# or is a script without a #! line.
try:
argv = shlex.split(args.power_cycle_cmd)
if not argv:
raise ValueError("empty command")
r = subprocess.run(argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except (OSError, ValueError) as e:
log("WARNING: could not run power-cycle command (%s); "
"continuing to watch console" % e)
else:
log("power-cycle rc=%d: %s" % (r.returncode,
r.stdout.decode(errors="replace").strip()))
if r.returncode != 0:
log("WARNING: power-cycle command returned non-zero; continuing to watch console")
else:
log("no --power-cycle-cmd given: power-cycle or reset the board now "
"if it is not already booting")
Expand Down
Loading