diff --git a/board/main.c b/board/main.c index a745403da754cc..2b6c78a94a82a7 100644 --- a/board/main.c +++ b/board/main.c @@ -39,6 +39,8 @@ #include "drivers/can.h" +extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used + struct __attribute__((packed)) health_t { uint32_t uptime_pkt; uint32_t voltage_pkt; @@ -364,6 +366,24 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) case 0xd2: resp_len = get_health_pkt(resp); break; + // **** 0xd3: get first 64 bytes of signature + case 0xd3: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len], resp_len); + } + break; + // **** 0xd4: get second 64 bytes of signature + case 0xd4: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len + 64], resp_len); + } + break; // **** 0xd6: get version case 0xd6: COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN); diff --git a/python/__init__.py b/python/__init__.py index ee9db8d6b49b96..8f4ae29181bb69 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -379,6 +379,17 @@ def enter_bootloader(self): def get_version(self): return self._handle.controlRead(Panda.REQUEST_IN, 0xd6, 0, 0, 0x40).decode('utf8') + @staticmethod + def get_signature_from_firmware(fn): + f = open(fn, 'rb') + f.seek(-128, 2) # Seek from end of file + return f.read(128) + + def get_signature(self): + part_1 = self._handle.controlRead(Panda.REQUEST_IN, 0xd3, 0, 0, 0x40) + part_2 = self._handle.controlRead(Panda.REQUEST_IN, 0xd4, 0, 0, 0x40) + return part_1 + part_2 + def get_type(self): return self._handle.controlRead(Panda.REQUEST_IN, 0xc1, 0, 0, 0x40) diff --git a/tests/automated/1_program.py b/tests/automated/1_program.py index a1486660135ac6..98c32114fe7bb7 100644 --- a/tests/automated/1_program.py +++ b/tests/automated/1_program.py @@ -1,15 +1,34 @@ +import os + +from nose.tools import assert_equal + +from panda import Panda, BASEDIR from .helpers import reset_pandas, test_all_pandas, panda_connect_and_init + # Reset the pandas before flashing them def aaaa_reset_before_tests(): reset_pandas() + @test_all_pandas @panda_connect_and_init def test_recover(p): assert p.recover(timeout=30) + @test_all_pandas @panda_connect_and_init def test_flash(p): p.flash() + + +@test_all_pandas +@panda_connect_and_init +def test_get_signature(p): + fn = os.path.join(BASEDIR, "board/obj/panda.bin") + + firmware_sig = Panda.get_signature_from_firmware(fn) + panda_sig = p.get_signature() + + assert_equal(panda_sig, firmware_sig)