mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-21 16:23:46 +08:00
Harden Rivian angle and bridge safety
Keep Rivian angle commands below 4 m/s², exercise the common angle-safety coverage, and prevent generic firmware management from overwriting unverified external Black Pandas. Original safety work based on PR #90 by TonyJOM (Anthony Orta). Co-authored-by: TonyJOM <anthonyorta20@icloud.com>
This commit is contained in:
@@ -77,13 +77,13 @@ def _flash_panda(panda: Panda) -> None:
|
||||
def is_rivian_bridge_panda(panda: Panda, rivian: bool | None = None) -> bool:
|
||||
if panda.is_internal() or panda.get_type() != Panda.HW_TYPE_BLACK:
|
||||
return False
|
||||
if rivian is None:
|
||||
rivian = _is_rivian()
|
||||
if rivian or panda.bootstub:
|
||||
return rivian
|
||||
# A cached Rivian CarParams record is not sufficient evidence to identify a
|
||||
# bridge. An arbitrary external Black Panda may be connected at the same
|
||||
# time, and flashing it would permanently replace its firmware. Only the
|
||||
# signed bridge image can positively identify the hardware.
|
||||
try:
|
||||
expected_signature = Panda.get_signature_from_firmware(FW_PATH)
|
||||
return panda.get_signature() == expected_signature
|
||||
return not panda.bootstub and panda.get_signature() == expected_signature
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@@ -108,12 +108,14 @@ def prepare_rivian_bridge(panda_serials: list[str]) -> set[str]:
|
||||
continue
|
||||
|
||||
bridge_confirmed = is_rivian_bridge_panda(panda, rivian)
|
||||
if not bridge_confirmed:
|
||||
if not bridge_confirmed and not rivian:
|
||||
continue
|
||||
|
||||
bridge_serials.add(serial)
|
||||
if rivian and firmware_available:
|
||||
if bridge_confirmed and rivian and firmware_available:
|
||||
_flash_panda(panda)
|
||||
elif rivian:
|
||||
cloudlog.warning(f"External Black Panda {serial} is not signed with the Rivian bridge firmware; leaving it untouched")
|
||||
except Exception:
|
||||
cloudlog.exception(f"Failed to prepare Rivian Extreme harness bridge {serial}")
|
||||
finally:
|
||||
|
||||
@@ -46,8 +46,10 @@ def test_outdated_rivian_bridge_uses_bridge_flash_path():
|
||||
panda_class.usb_list.return_value = ["bridge"]
|
||||
panda_class.get_signature_from_firmware.return_value = b"expected"
|
||||
|
||||
# An unknown firmware image cannot be safely identified as the bridge and
|
||||
# must be left to explicit provisioning instead of being overwritten.
|
||||
assert flasher.prepare_rivian_bridge(["internal", "bridge"]) == {"bridge"}
|
||||
flash_panda.assert_called_once_with(panda)
|
||||
flash_panda.assert_not_called()
|
||||
|
||||
|
||||
def test_non_rivian_matching_bridge_is_reserved_without_flashing():
|
||||
@@ -78,3 +80,18 @@ def test_non_rivian_external_black_panda_is_not_misidentified():
|
||||
|
||||
assert flasher.prepare_rivian_bridge(["internal", "external"]) == set()
|
||||
flash_panda.assert_not_called()
|
||||
|
||||
|
||||
def test_bootstub_external_black_panda_is_not_misidentified():
|
||||
panda = _external_black_panda(signature=b"expected", bootstub=True)
|
||||
with patch.object(flasher, "_is_rivian", return_value=True), \
|
||||
patch.object(flasher.os.path, "isfile", return_value=True), \
|
||||
patch.object(flasher, "Panda", wraps=flasher.Panda) as panda_class, \
|
||||
patch.object(flasher, "_flash_panda") as flash_panda:
|
||||
panda_class.return_value = panda
|
||||
panda_class.HW_TYPE_BLACK = b"\x03"
|
||||
panda_class.usb_list.return_value = ["bridge"]
|
||||
panda_class.get_signature_from_firmware.return_value = b"expected"
|
||||
|
||||
assert flasher.prepare_rivian_bridge(["bridge"]) == {"bridge"}
|
||||
flash_panda.assert_not_called()
|
||||
|
||||
Reference in New Issue
Block a user