Switch panda to scons builder (#635)

* add scons builder

* cleanup 1

* remove building from python code

* add pedal build

* fixup flags

* add EON flag

* change github actions to scons

* fixup automated tests

* move flashing scripts

* fix indent

* remove version.mk

* fix not in git

* fix linker script filename

* untested pedal flashing scripts

* add release option

* better asserts

* swap condition

* enable usb and fix flash script

* usb flash is not supported

* use button to enable dfu mode

* no usb because misra

* remove sleep
master
Willem Melching 2021-03-24 14:44:32 +01:00 committed by GitHub
parent d572c012cb
commit ad9ecefe65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 206 additions and 280 deletions

View File

@ -36,14 +36,10 @@ jobs:
run: eval "$BUILD"
- name: Test python package installer
run: $RUN "cd /tmp/openpilot/panda && python setup.py install"
- name: Build panda STM image
run: $RUN "cd /tmp/openpilot/panda/board && make bin"
- name: Build panda STM bootstub image
run: $RUN "cd /tmp/openpilot/panda/board && make obj/bootstub.panda.bin"
- name: Build pedal STM image
run: $RUN "cd /tmp/openpilot/panda/board/pedal && make obj/comma.bin"
- name: Build pedal STM bootstub image
run: $RUN "cd /tmp/openpilot/panda/board/pedal && make obj/bootstub.bin"
- name: Build panda STM image and bootstub
run: $RUN "cd /tmp/openpilot/panda && scons"
- name: Build pedal STM image and bootstub
run: $RUN "cd /tmp/openpilot/panda && PEDAL=1 scons"
safety:
name: safety

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ examples/output.csv
.vscode*
nosetests.xml
.mypy_cache/
.sconsign.dblite

4
Jenkinsfile vendored
View File

@ -25,7 +25,7 @@ pipeline {
lock(resource: "Pandas", inversePrecedence: true, quantity: 1){
timeout(time: 60, unit: 'MINUTES') {
script {
sh "docker run --name ${env.DOCKER_NAME} --privileged --volume /dev/bus/usb:/dev/bus/usb --volume /var/run/dbus:/var/run/dbus --net host ${env.DOCKER_IMAGE_TAG} bash -c 'cd /tmp/panda; ./run_automated_tests.sh'"
sh "docker run --name ${env.DOCKER_NAME} --privileged --volume /dev/bus/usb:/dev/bus/usb --volume /var/run/dbus:/var/run/dbus --net host ${env.DOCKER_IMAGE_TAG} bash -c 'cd /tmp/panda; scons; ./run_automated_tests.sh'"
sh "docker cp ${env.DOCKER_NAME}:/tmp/panda/nosetests.xml test_results_dev.xml"
sh "docker rm ${env.DOCKER_NAME}"
}
@ -38,7 +38,7 @@ pipeline {
lock(resource: "Pandas", inversePrecedence: true, quantity: 1){
timeout(time: 60, unit: 'MINUTES') {
script {
sh "docker run --name ${env.DOCKER_NAME} --privileged --volume /dev/bus/usb:/dev/bus/usb --volume /var/run/dbus:/var/run/dbus --net host ${env.DOCKER_IMAGE_TAG} bash -c 'touch /EON; cd /tmp/panda; ./run_automated_tests.sh'"
sh "docker run --name ${env.DOCKER_NAME} --privileged --volume /dev/bus/usb:/dev/bus/usb --volume /var/run/dbus:/var/run/dbus --net host ${env.DOCKER_IMAGE_TAG} bash -c 'touch /EON; cd /tmp/panda; scons; ./run_automated_tests.sh'"
sh "docker cp ${env.DOCKER_NAME}:/tmp/panda/nosetests.xml test_results_eon.xml"
sh "docker rm ${env.DOCKER_NAME}"
}

1
SConstruct 100644
View File

@ -0,0 +1 @@
SConscript('board/SConscript')

View File

@ -1,3 +1,3 @@
# flake8: noqa
# pylint: skip-file
from .python import Panda, PandaWifiStreaming, PandaDFU, flash_release, BASEDIR, ensure_st_up_to_date, build_st, PandaSerial
from .python import Panda, PandaWifiStreaming, PandaDFU, flash_release, BASEDIR, ensure_st_up_to_date, PandaSerial

View File

@ -1,8 +0,0 @@
PROJ_NAME = panda
CFLAGS = -g -Wall -Wextra -Wstrict-prototypes -Werror
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4
CFLAGS += -mhard-float -DSTM32F4 -DSTM32F413xx -mfpu=fpv4-sp-d16 -fsingle-precision-constant
STARTUP_FILE = startup_stm32f413xx
include build.mk

156
board/SConscript 100644
View File

@ -0,0 +1,156 @@
import os
import subprocess
EON = os.path.isfile('/EON')
TICI = os.path.isfile('/TICI')
PC = not (EON or TICI)
PREFIX = "arm-none-eabi-"
BUILDER = "DEV"
if os.getenv("PEDAL"):
PROJECT = "pedal"
STARTUP_FILE = "startup_stm32f205xx.s"
MAIN = "pedal/main.c"
PROJECT_FLAGS = [
"-mcpu=cortex-m3",
"-msoft-float",
"-DSTM32F2",
"-DSTM32F205xx",
"-O2",
"-DPEDAL",
]
else:
PROJECT = "panda"
STARTUP_FILE = "startup_stm32f413xx.s"
MAIN = "main.c"
PROJECT_FLAGS = [
"-mcpu=cortex-m4",
"-mhard-float",
"-DSTM32F4",
"-DSTM32F413xx",
"-mfpu=fpv4-sp-d16",
"-fsingle-precision-constant",
"-Os",
"-g",
]
if not PC:
PROJECT_FLAGS += ["-DEON"]
BUILDER = "EON"
def get_version(builder, build_type):
version_file = File('../VERSION').srcnode().abspath
version = open(version_file).read()
try:
git = subprocess.check_output(["git", "rev-parse", "--short=8", "HEAD"], encoding='utf8').strip()
except subprocess.CalledProcessError:
git = "unknown"
return f"{version}-{builder}-{git}-{build_type}"
def to_c_uint32(x):
nums = []
for _ in range(0x20):
nums.append(x % (2**32))
x //= (2**32)
return "{" + 'U,'.join(map(str, nums)) + "U}"
def get_key_header(name):
from Crypto.PublicKey import RSA
public_fn = File(f'../certs/{name}.pub').srcnode().abspath
rsa = RSA.importKey(open(public_fn).read())
assert(rsa.size_in_bits() == 1024)
rr = pow(2**1024, 2, rsa.n)
n0inv = 2**32 - pow(rsa.n, -1, 2**32)
r = [
f"RSAPublicKey {name}_rsa_key = {{",
f" .len = 0x20,",
f" .n0inv = {n0inv}U,",
f" .n = {to_c_uint32(rsa.n)},",
f" .rr = {to_c_uint32(rr)},",
f" .exponent = {rsa.e},",
f"}};",
]
return r
def objcopy(source, target, env, for_signature):
return '$OBJCOPY -O binary %s %s' % (source[0], target[0])
linkerscript_fn = File("stm32_flash.ld").srcnode().abspath
flags = [
"-Wall",
"-Wextra",
"-Wstrict-prototypes",
"-Werror",
"-mlittle-endian",
"-mthumb",
"-nostdlib",
"-fno-builtin",
f"-T{linkerscript_fn}",
"-std=gnu11",
] + PROJECT_FLAGS
if os.getenv("RELEASE"):
BUILD_TYPE = "RELEASE"
cert_fn = os.getenv("CERT")
assert cert_fn is not None, 'No certificate file specified. Please set CERT env variable'
assert os.path.exists(cert_fn), 'Certificate file not found. Please specify absolute path'
else:
BUILD_TYPE = "DEBUG"
cert_fn = File("../certs/debug").srcnode().abspath
flags += ["-DALLOW_DEBUG"]
includes = [
"inc",
"..",
".",
]
panda_env = Environment(
ENV=os.environ,
CC=PREFIX + 'gcc',
AS=PREFIX + 'gcc',
OBJCOPY=PREFIX + 'objcopy',
OBJDUMP=PREFIX + 'objdump',
ASCOM="$AS $ASFLAGS -o $TARGET -c $SOURCES",
CFLAGS=flags,
ASFLAGS=flags,
LINKFLAGS=flags,
CPPPATH=includes,
BUILDERS={
'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf')
}
)
# Common autogenerated includes
version = f'const uint8_t gitversion[] = "{get_version(BUILDER, BUILD_TYPE)}";'
gitversion = panda_env.Textfile("obj/gitversion.h", [version, ""])
certs = [get_key_header(n) for n in ["debug", "release"]]
certheader = panda_env.Textfile("obj/cert.h", certs + [""])
startup = panda_env.Object(STARTUP_FILE)
# Bootstub
crypto = ["../crypto/rsa.c", "../crypto/sha.c"]
bootstub_elf = panda_env.Program(f"obj/bootstub.{PROJECT}.elf", [startup] + crypto + ["bootstub.c"])
bootstub_bin = panda_env.Objcopy(f"obj/bootstub.{PROJECT}.bin", bootstub_elf)
# Build main
main_elf = panda_env.Program(f"obj/{PROJECT}.elf", [startup, MAIN],
LINKFLAGS=["-Wl,--section-start,.isr_vector=0x8004000"] + flags)
main_bin = panda_env.Objcopy(f"obj/{PROJECT}.bin", main_elf)
# Sign main
sign_py = File("../crypto/sign.py").srcnode().abspath
panda_bin_signed = panda_env.Command(f"obj/{PROJECT}.bin.signed", main_bin, f"SETLEN=1 {sign_py} $SOURCE $TARGET {cert_fn}")

View File

@ -1,91 +0,0 @@
CFLAGS += -I inc -I ../ -nostdlib -fno-builtin -std=gnu11 -Os
CFLAGS += -Tstm32_flash.ld
DFU_UTIL = "dfu-util"
PC = 0
ifeq (,$(wildcard /EON))
ifeq (,$(wildcard /TICI))
PC = 1
endif
endif
ifeq (1, $(PC))
BUILDER = DEV
else
CFLAGS += "-DEON"
BUILDER = EON
endif
#COMPILER_PATH = /home/batman/Downloads/gcc-arm-none-eabi-9-2020-q2-update/bin/
CC = $(COMPILER_PATH)arm-none-eabi-gcc
OBJCOPY = $(COMPILER_PATH)arm-none-eabi-objcopy
OBJDUMP = $(COMPILER_PATH)arm-none-eabi-objdump
ifeq ($(RELEASE),1)
CERT = ../../pandaextra/certs/release
else
# enable the debug cert
CERT = ../certs/debug
CFLAGS += "-DALLOW_DEBUG"
endif
DEPDIR = generated_dependencies
$(shell mkdir -p -m 777 $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
POSTCOMPILE = @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@
# this no longer pushes the bootstub
flash: obj/$(PROJ_NAME).bin
PYTHONPATH=../ python3 -c "from python import Panda; Panda().flash('obj/$(PROJ_NAME).bin')"
ota: obj/$(PROJ_NAME).bin
curl http://192.168.0.10/stupdate --upload-file $<
bin: obj/$(PROJ_NAME).bin
# this flashes everything
recover: obj/bootstub.$(PROJ_NAME).bin obj/$(PROJ_NAME).bin
-PYTHONPATH=../ python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)"
sleep 1.0
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08004000 -D obj/$(PROJ_NAME).bin
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.$(PROJ_NAME).bin
include ../common/version.mk
obj/cert.h: ../crypto/getcertheader.py
../crypto/getcertheader.py ../certs/debug.pub ../certs/release.pub > $@
obj/%.$(PROJ_NAME).o: %.c obj/gitversion.h obj/cert.h $(DEPDIR)/%.d
$(CC) $(DEPFLAGS) $(CFLAGS) -o $@ -c $<
$(POSTCOMPILE)
obj/%.$(PROJ_NAME).o: ../crypto/%.c
$(CC) $(CFLAGS) -o $@ -c $<
obj/$(STARTUP_FILE).o: $(STARTUP_FILE).s
$(CC) $(CFLAGS) -o $@ -c $<
obj/$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/main.$(PROJ_NAME).o
# hack
$(CC) -Wl,--section-start,.isr_vector=0x8004000 $(CFLAGS) -o obj/$(PROJ_NAME).elf $^
$(OBJCOPY) -v -O binary obj/$(PROJ_NAME).elf obj/code.bin
SETLEN=1 ../crypto/sign.py obj/code.bin $@ $(CERT)
@BINSIZE=$$(du -b "obj/$(PROJ_NAME).bin" | cut -f 1) ; \
if [ $$BINSIZE -ge 49152 ]; then echo "ERROR obj/$(PROJ_NAME).bin is too big!"; exit 1; fi;
obj/bootstub.$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/bootstub.$(PROJ_NAME).o obj/sha.$(PROJ_NAME).o obj/rsa.$(PROJ_NAME).o
$(CC) $(CFLAGS) -o obj/bootstub.$(PROJ_NAME).elf $^
$(OBJCOPY) -v -O binary obj/bootstub.$(PROJ_NAME).elf $@
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(wildcard *.c))))
clean:
@$(RM) obj/*
@rm -rf $(DEPDIR)

5
board/flash.sh 100755
View File

@ -0,0 +1,5 @@
#!/usr/bin/env sh
set -e
scons -u
PYTHONPATH=.. python3 -c "from python import Panda; Panda().flash('obj/panda.bin.signed')"

View File

@ -1,67 +0,0 @@
# :set noet
PROJ_NAME = comma
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -Werror -std=gnu11 -DPEDAL
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3
CFLAGS += -msoft-float -DSTM32F2 -DSTM32F205xx
CFLAGS += -I ../inc -I ../ -I ../../ -nostdlib -fno-builtin
CFLAGS += -T../stm32_flash.ld
STARTUP_FILE = startup_stm32f205xx
CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump
DFU_UTIL = "dfu-util"
# pedal only uses the debug cert
CERT = ../../certs/debug
CFLAGS += "-DALLOW_DEBUG"
canflash: obj/$(PROJ_NAME).bin
../../tests/pedal/enter_canloader.py $<
usbflash: obj/$(PROJ_NAME).bin
../../tests/pedal/enter_canloader.py; sleep 0.5
PYTHONPATH=../../ python -c "from python import Panda; p = [x for x in [Panda(x) for x in Panda.list()] if x.bootstub]; assert(len(p)==1); p[0].flash('obj/$(PROJ_NAME).bin', reconnect=False)"
recover: obj/bootstub.bin obj/$(PROJ_NAME).bin
../../tests/pedal/enter_canloader.py --recover; sleep 0.5
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08004000 -D obj/$(PROJ_NAME).bin
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.bin
include ../../common/version.mk
obj/cert.h: ../../crypto/getcertheader.py
../../crypto/getcertheader.py ../../certs/debug.pub ../../certs/release.pub > $@
obj/main.o: main.c ../*.h
mkdir -p obj
$(CC) $(CFLAGS) -o $@ -c $<
obj/bootstub.o: ../bootstub.c ../*.h obj/gitversion.h obj/cert.h
mkdir -p obj
mkdir -p ../obj
cp obj/gitversion.h ../obj/gitversion.h
cp obj/cert.h ../obj/cert.h
$(CC) $(CFLAGS) -o $@ -c $<
obj/$(STARTUP_FILE).o: ../$(STARTUP_FILE).s
$(CC) $(CFLAGS) -o $@ -c $<
obj/%.o: ../../crypto/%.c
$(CC) $(CFLAGS) -o $@ -c $<
obj/$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/main.o
# hack
$(CC) -Wl,--section-start,.isr_vector=0x8004000 $(CFLAGS) -o obj/$(PROJ_NAME).elf $^
$(OBJCOPY) -v -O binary obj/$(PROJ_NAME).elf obj/code.bin
SETLEN=1 ../../crypto/sign.py obj/code.bin $@ $(CERT)
obj/bootstub.bin: obj/$(STARTUP_FILE).o obj/bootstub.o obj/sha.o obj/rsa.o
$(CC) $(CFLAGS) -o obj/bootstub.$(PROJ_NAME).elf $^
$(OBJCOPY) -v -O binary obj/bootstub.$(PROJ_NAME).elf $@
clean:
rm -f obj/*

View File

@ -0,0 +1,8 @@
#!/usr/bin/env sh
set -e
cd ..
PEDAL=1 scons -u
cd pedal
../../tests/pedal/enter_canloader.py ../obj/pedal.bin.signed

View File

@ -0,0 +1,11 @@
#!/usr/bin/env sh
set -e
DFU_UTIL="dfu-util"
cd ..
PEDAL=1 scons -u
cd pedal
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D ../obj/pedal.bin.signed
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D ../obj/bootstub.pedal.bin

11
board/recover.sh 100755
View File

@ -0,0 +1,11 @@
#!/usr/bin/env sh
set -e
DFU_UTIL="dfu-util"
scons -u
PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)"
sleep 1
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/panda.bin.signed
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda.bin

View File

@ -1,20 +0,0 @@
ifeq ($(RELEASE),1)
BUILD_TYPE = "RELEASE"
else
BUILD_TYPE = "DEBUG"
endif
SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
ifneq ($(wildcard $(SELF_DIR)/../.git/HEAD),)
obj/gitversion.h: $(SELF_DIR)/../VERSION $(SELF_DIR)/../.git/HEAD $(SELF_DIR)/../.git/index
echo "const uint8_t gitversion[] = \"$(shell cat $(SELF_DIR)/../VERSION)-$(BUILDER)-$(shell git rev-parse --short=8 HEAD)-$(BUILD_TYPE)\";" > $@
else
ifneq ($(wildcard $(SELF_DIR)/../../.git/modules/panda/HEAD),)
obj/gitversion.h: $(SELF_DIR)/../VERSION $(SELF_DIR)/../../.git/modules/panda/HEAD $(SELF_DIR)/../../.git/modules/panda/index
echo "const uint8_t gitversion[] = \"$(shell cat $(SELF_DIR)/../VERSION)-$(BUILDER)-$(shell git rev-parse --short=8 HEAD)-$(BUILD_TYPE)\";" > $@
else
obj/gitversion.h: $(SELF_DIR)/../VERSION
echo "const uint8_t gitversion[] = \"$(shell cat $(SELF_DIR)/../VERSION)-$(BUILDER)-unknown-$(BUILD_TYPE)\";" > $@
endif
endif

View File

@ -1,43 +0,0 @@
#!/usr/bin/env python3
import sys
from Crypto.PublicKey import RSA
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, _ = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
def to_c_string(x):
mod = (hex(x)[2:-1].rjust(0x100, '0'))
hh = ''.join('\\x' + mod[i:i + 2] for i in range(0, 0x100, 2))
return hh
def to_c_uint32(x):
nums = []
for _ in range(0x20):
nums.append(x % (2**32))
x //= (2**32)
return "{" + 'U,'.join(map(str, nums)) + "U}"
for fn in sys.argv[1:]:
rsa = RSA.importKey(open(fn).read())
rr = pow(2**1024, 2, rsa.n)
n0inv = 2**32 - modinv(rsa.n, 2**32)
cname = fn.split("/")[-1].split(".")[0] + "_rsa_key"
print('RSAPublicKey ' + cname + ' = {.len = 0x20,')
print(' .n0inv = %dU,' % n0inv)
print(' .n = %s,' % to_c_uint32(rsa.n))
print(' .rr = %s,' % to_c_uint32(rr))
print(' .exponent = %d,' % rsa.e)
print('};')

View File

@ -7,7 +7,6 @@ import usb1
import os
import time
import traceback
import subprocess
import sys
from .dfu import PandaDFU # pylint: disable=import-error
from .flash_release import flash_release # noqa pylint: disable=import-error
@ -19,17 +18,10 @@ from .isotp import isotp_send, isotp_recv # pylint: disable=import-error
__version__ = '0.0.9'
BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
DEFAULT_FW_FN = os.path.join(BASEDIR, "board", "obj", "panda.bin.signed")
DEBUG = os.getenv("PANDADEBUG") is not None
# *** wifi mode ***
def build_st(target, mkfile="Makefile", clean=True):
from panda import BASEDIR
clean_cmd = "make -f %s clean" % mkfile if clean else ":"
cmd = 'cd %s && %s && make -f %s %s' % (os.path.join(BASEDIR, "board"), clean_cmd, mkfile, target)
_ = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
def parse_can_buffer(dat):
ret = []
for j in range(0, len(dat), 0x10):
@ -184,7 +176,6 @@ class Panda(object):
if self._serial is None or this_serial == self._serial:
self._serial = this_serial
print("opening device", self._serial, hex(device.getProductID()))
time.sleep(1)
self.bootstub = device.getProductID() == 0xddee
self.legacy = (device.getbcdDevice() != 0x2300)
self._handle = device.open()
@ -267,23 +258,12 @@ class Panda(object):
except Exception:
pass
def flash(self, fn=None, code=None, reconnect=True):
def flash(self, fn=DEFAULT_FW_FN, code=None, reconnect=True):
print("flash: main version is " + self.get_version())
if not self.bootstub:
self.reset(enter_bootstub=True)
assert(self.bootstub)
if fn is None and code is None:
if self.legacy:
fn = "obj/comma.bin"
print("building legacy st code")
build_st(fn, "Makefile.legacy")
else:
fn = "obj/panda.bin"
print("building panda st code")
build_st(fn)
fn = os.path.join(BASEDIR, "board", fn)
if code is None:
with open(fn, "rb") as f:
code = f.read()

View File

@ -92,16 +92,8 @@ class PandaDFU(object):
self.reset()
def recover(self):
from panda import BASEDIR, build_st
if self.legacy:
fn = "obj/bootstub.comma.bin"
print("building legacy bootstub")
build_st(fn, "Makefile.legacy")
else:
fn = "obj/bootstub.panda.bin"
print("building panda bootstub")
build_st(fn)
fn = os.path.join(BASEDIR, "board", fn)
from panda import BASEDIR
fn = os.path.join(BASEDIR, "board", "obj", "bootstub.panda.bin")
with open(fn, "rb") as f:
code = f.read()

View File

@ -11,3 +11,4 @@ cffi==1.14.3
crcmod
pre-commit==2.4.0
pylint==2.5.2
scons==4.1.0.post1

View File

@ -1,7 +0,0 @@
from panda import build_st
def test_build_panda():
build_st("obj/panda.bin")
def test_build_bootstub_panda():
build_st("obj/bootstub.panda.bin")

View File

@ -26,7 +26,7 @@ def test_flash(p):
@test_all_pandas
@panda_connect_and_init
def test_get_signature(p):
fn = os.path.join(BASEDIR, "board/obj/panda.bin")
fn = os.path.join(BASEDIR, "board/obj/panda.bin.signed")
firmware_sig = Panda.get_signature_from_firmware(fn)
panda_sig = p.get_signature()