From 0e14545d48048a0926e48f3ff4ba9525f125d437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 15 Oct 2021 14:05:14 +0300 Subject: [PATCH] [FL-1945] Firmware, Scripts, Cli: add OTPv2, alternative displays support and 2-step OTP programming. #764 --- applications/cli/cli_commands.c | 16 +- .../targets/f6/furi-hal/furi-hal-version.c | 112 +++++++++---- .../targets/f7/furi-hal/furi-hal-version.c | 112 +++++++++---- .../furi-hal-include/furi-hal-version.h | 28 ++++ scripts/otp.py | 152 +++++++++++++----- 5 files changed, 322 insertions(+), 98 deletions(-) diff --git a/applications/cli/cli_commands.c b/applications/cli/cli_commands.c index 255ab3cc..59733cf6 100644 --- a/applications/cli/cli_commands.c +++ b/applications/cli/cli_commands.c @@ -57,10 +57,6 @@ static const uint8_t enclave_signature_expected[ENCLAVE_SIGNATURE_KEY_SLOTS][ENC void cli_command_device_info(Cli* cli, string_t args, void* context) { // Model name printf("hardware_model : %s\r\n", furi_hal_version_get_model_name()); - const char* name = furi_hal_version_get_name_ptr(); - if(name) { - printf("hardware_name : %s\r\n", name); - } // Unique ID printf("hardware_uid : "); @@ -70,16 +66,24 @@ void cli_command_device_info(Cli* cli, string_t args, void* context) { } printf("\r\n"); + // OTP Revision + printf("hardware_otp_ver : %d\r\n", furi_hal_version_get_otp_version()); + printf("hardware_timestamp : %lu\r\n", furi_hal_version_get_hw_timestamp()); + // Board Revision printf("hardware_ver : %d\r\n", furi_hal_version_get_hw_version()); printf("hardware_target : %d\r\n", furi_hal_version_get_hw_target()); printf("hardware_body : %d\r\n", furi_hal_version_get_hw_body()); printf("hardware_connect : %d\r\n", furi_hal_version_get_hw_connect()); - printf("hardware_timestamp : %lu\r\n", furi_hal_version_get_hw_timestamp()); + printf("hardware_display : %d\r\n", furi_hal_version_get_hw_display()); - // Color and Region + // Board Personification printf("hardware_color : %d\r\n", furi_hal_version_get_hw_color()); printf("hardware_region : %d\r\n", furi_hal_version_get_hw_region()); + const char* name = furi_hal_version_get_name_ptr(); + if(name) { + printf("hardware_name : %s\r\n", name); + } // Bootloader Version const Version* boot_version = furi_hal_version_get_boot_version(); diff --git a/firmware/targets/f6/furi-hal/furi-hal-version.c b/firmware/targets/f6/furi-hal/furi-hal-version.c index 93166b16..7ee67c2a 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-version.c +++ b/firmware/targets/f6/furi-hal/furi-hal-version.c @@ -10,13 +10,6 @@ #define FURI_HAL_VERSION_OTP_HEADER_MAGIC 0xBABE #define FURI_HAL_VERSION_OTP_ADDRESS OTP_AREA_BASE -/** OTP Versions enum */ -typedef enum { - FuriHalVersionOtpVersion0=0x00, - FuriHalVersionOtpVersion1=0x01, - FuriHalVersionOtpVersionEmpty=0xFFFFFFFE, - FuriHalVersionOtpVersionUnknown=0xFFFFFFFF, -} FuriHalVersionOtpVersion; /** OTP V0 Structure: prototypes and early EVT */ typedef struct { @@ -28,7 +21,7 @@ typedef struct { char name[FURI_HAL_VERSION_NAME_LENGTH]; } FuriHalVersionOTPv0; -/** OTP V1 Structure: late EVT, DVT, PVT, Production */ +/** OTP V1 Structure: late EVT, DVT */ typedef struct { /* First 64 bits: header */ uint16_t header_magic; @@ -49,10 +42,35 @@ typedef struct { char name[FURI_HAL_VERSION_NAME_LENGTH]; /** Unique Device Name */ } FuriHalVersionOTPv1; +/** OTP V2 Structure: DVT2, PVT, Production */ +typedef struct { + /* Early First 64 bits: header */ + uint16_t header_magic; + uint8_t header_version; + uint8_t header_reserved; + uint32_t header_timestamp; + + /* Early Second 64 bits: board info */ + uint8_t board_version; /** Board version */ + uint8_t board_target; /** Board target firmware */ + uint8_t board_body; /** Board body */ + uint8_t board_connect; /** Board interconnect */ + uint8_t board_display; /** Board display */ + uint8_t board_reserved2_0; /** Reserved for future use, 0x00 */ + uint16_t board_reserved2_1; /** Reserved for future use, 0x0000 */ + + /* Late Third 64 bits: device info */ + uint8_t board_color; /** Board color */ + uint8_t board_region; /** Board region */ + uint16_t board_reserved3_0; /** Reserved for future use, 0x0000 */ + uint32_t board_reserved3_1; /** Reserved for future use, 0x00000000 */ + + /* Late Fourth 64 bits: Unique Device Name */ + char name[FURI_HAL_VERSION_NAME_LENGTH]; /** Unique Device Name */ +} FuriHalVersionOTPv2; + /** Represenation Model: */ typedef struct { - FuriHalVersionOtpVersion otp_version; - uint32_t timestamp; uint8_t board_version; /** Board version */ @@ -61,6 +79,7 @@ typedef struct { uint8_t board_connect; /** Board interconnect */ uint8_t board_color; /** Board color */ uint8_t board_region; /** Board region */ + uint8_t board_display; /** Board display */ char name[FURI_HAL_VERSION_ARRAY_NAME_LENGTH]; /** \0 terminated name */ char device_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; /** device name for special needs */ @@ -69,20 +88,6 @@ typedef struct { static FuriHalVersion furi_hal_version = {0}; -static FuriHalVersionOtpVersion furi_hal_version_get_otp_version() { - if (*(uint64_t*)FURI_HAL_VERSION_OTP_ADDRESS == 0xFFFFFFFF) { - return FuriHalVersionOtpVersionEmpty; - } else { - if (((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_magic == FURI_HAL_VERSION_OTP_HEADER_MAGIC) { - return FuriHalVersionOtpVersion1; - } else if (((FuriHalVersionOTPv0*)FURI_HAL_VERSION_OTP_ADDRESS)->board_version <= 10) { - return FuriHalVersionOtpVersion0; - } else { - return FuriHalVersionOtpVersionUnknown; - } - } -} - static void furi_hal_version_set_name(const char* name) { if(name != NULL) { strlcpy(furi_hal_version.name, name, FURI_HAL_VERSION_ARRAY_NAME_LENGTH); @@ -124,8 +129,6 @@ static void furi_hal_version_load_otp_v0() { furi_hal_version.board_target = otp->board_target; furi_hal_version.board_body = otp->board_body; furi_hal_version.board_connect = otp->board_connect; - furi_hal_version.board_color = 0; - furi_hal_version.board_region = 0; furi_hal_version_set_name(otp->name); } @@ -144,9 +147,33 @@ static void furi_hal_version_load_otp_v1() { furi_hal_version_set_name(otp->name); } +static void furi_hal_version_load_otp_v2() { + const FuriHalVersionOTPv2* otp = (FuriHalVersionOTPv2*)FURI_HAL_VERSION_OTP_ADDRESS; + + // 1st block, programmed afer baking + furi_hal_version.timestamp = otp->header_timestamp; + + // 2nd block, programmed afer baking + furi_hal_version.board_version = otp->board_version; + furi_hal_version.board_target = otp->board_target; + furi_hal_version.board_body = otp->board_body; + furi_hal_version.board_connect = otp->board_connect; + furi_hal_version.board_display = otp->board_display; + + // 3rd and 4th blocks, programmed on FATP stage + if (otp->board_color != 0xFF) { + furi_hal_version.board_color = otp->board_color; + furi_hal_version.board_region = otp->board_region; + furi_hal_version_set_name(otp->name); + } else { + furi_hal_version.board_color = 0; + furi_hal_version.board_region = 0; + furi_hal_version_set_name(NULL); + } +} + void furi_hal_version_init() { - furi_hal_version.otp_version = furi_hal_version_get_otp_version(); - switch(furi_hal_version.otp_version) { + switch(furi_hal_version_get_otp_version()) { case FuriHalVersionOtpVersionUnknown: furi_hal_version_load_otp_default(); break; @@ -159,6 +186,9 @@ void furi_hal_version_init() { case FuriHalVersionOtpVersion1: furi_hal_version_load_otp_v1(); break; + case FuriHalVersionOtpVersion2: + furi_hal_version_load_otp_v2(); + break; default: furi_crash(NULL); } FURI_LOG_I("FuriHalVersion", "Init OK"); @@ -172,6 +202,28 @@ const char* furi_hal_version_get_model_name() { return "Flipper Zero"; } +const FuriHalVersionOtpVersion furi_hal_version_get_otp_version() { + if (*(uint64_t*)FURI_HAL_VERSION_OTP_ADDRESS == 0xFFFFFFFF) { + return FuriHalVersionOtpVersionEmpty; + } else { + if (((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_magic == FURI_HAL_VERSION_OTP_HEADER_MAGIC) { + // Version 1+ + uint8_t version = ((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_version; + if (version >= FuriHalVersionOtpVersion1 && version <= FuriHalVersionOtpVersion2) { + return version; + } else { + return FuriHalVersionOtpVersionUnknown; + } + } else if (((FuriHalVersionOTPv0*)FURI_HAL_VERSION_OTP_ADDRESS)->board_version <= 10) { + // Version 0 + return FuriHalVersionOtpVersion0; + } else { + // Version Unknown + return FuriHalVersionOtpVersionUnknown; + } + } +} + const uint8_t furi_hal_version_get_hw_version() { return furi_hal_version.board_version; } @@ -196,6 +248,10 @@ const FuriHalVersionRegion furi_hal_version_get_hw_region() { return furi_hal_version.board_region; } +const FuriHalVersionDisplay furi_hal_version_get_hw_display() { + return furi_hal_version.board_display; +} + const uint32_t furi_hal_version_get_hw_timestamp() { return furi_hal_version.timestamp; } diff --git a/firmware/targets/f7/furi-hal/furi-hal-version.c b/firmware/targets/f7/furi-hal/furi-hal-version.c index 5a98ab5e..64641fc6 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-version.c +++ b/firmware/targets/f7/furi-hal/furi-hal-version.c @@ -10,13 +10,6 @@ #define FURI_HAL_VERSION_OTP_HEADER_MAGIC 0xBABE #define FURI_HAL_VERSION_OTP_ADDRESS OTP_AREA_BASE -/** OTP Versions enum */ -typedef enum { - FuriHalVersionOtpVersion0=0x00, - FuriHalVersionOtpVersion1=0x01, - FuriHalVersionOtpVersionEmpty=0xFFFFFFFE, - FuriHalVersionOtpVersionUnknown=0xFFFFFFFF, -} FuriHalVersionOtpVersion; /** OTP V0 Structure: prototypes and early EVT */ typedef struct { @@ -28,7 +21,7 @@ typedef struct { char name[FURI_HAL_VERSION_NAME_LENGTH]; } FuriHalVersionOTPv0; -/** OTP V1 Structure: late EVT, DVT, PVT, Production */ +/** OTP V1 Structure: late EVT, DVT */ typedef struct { /* First 64 bits: header */ uint16_t header_magic; @@ -49,10 +42,35 @@ typedef struct { char name[FURI_HAL_VERSION_NAME_LENGTH]; /** Unique Device Name */ } FuriHalVersionOTPv1; +/** OTP V2 Structure: DVT2, PVT, Production */ +typedef struct { + /* Early First 64 bits: header */ + uint16_t header_magic; + uint8_t header_version; + uint8_t header_reserved; + uint32_t header_timestamp; + + /* Early Second 64 bits: board info */ + uint8_t board_version; /** Board version */ + uint8_t board_target; /** Board target firmware */ + uint8_t board_body; /** Board body */ + uint8_t board_connect; /** Board interconnect */ + uint8_t board_display; /** Board display */ + uint8_t board_reserved2_0; /** Reserved for future use, 0x00 */ + uint16_t board_reserved2_1; /** Reserved for future use, 0x0000 */ + + /* Late Third 64 bits: device info */ + uint8_t board_color; /** Board color */ + uint8_t board_region; /** Board region */ + uint16_t board_reserved3_0; /** Reserved for future use, 0x0000 */ + uint32_t board_reserved3_1; /** Reserved for future use, 0x00000000 */ + + /* Late Fourth 64 bits: Unique Device Name */ + char name[FURI_HAL_VERSION_NAME_LENGTH]; /** Unique Device Name */ +} FuriHalVersionOTPv2; + /** Represenation Model: */ typedef struct { - FuriHalVersionOtpVersion otp_version; - uint32_t timestamp; uint8_t board_version; /** Board version */ @@ -61,6 +79,7 @@ typedef struct { uint8_t board_connect; /** Board interconnect */ uint8_t board_color; /** Board color */ uint8_t board_region; /** Board region */ + uint8_t board_display; /** Board display */ char name[FURI_HAL_VERSION_ARRAY_NAME_LENGTH]; /** \0 terminated name */ char device_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; /** device name for special needs */ @@ -69,20 +88,6 @@ typedef struct { static FuriHalVersion furi_hal_version = {0}; -static FuriHalVersionOtpVersion furi_hal_version_get_otp_version() { - if (*(uint64_t*)FURI_HAL_VERSION_OTP_ADDRESS == 0xFFFFFFFF) { - return FuriHalVersionOtpVersionEmpty; - } else { - if (((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_magic == FURI_HAL_VERSION_OTP_HEADER_MAGIC) { - return FuriHalVersionOtpVersion1; - } else if (((FuriHalVersionOTPv0*)FURI_HAL_VERSION_OTP_ADDRESS)->board_version <= 10) { - return FuriHalVersionOtpVersion0; - } else { - return FuriHalVersionOtpVersionUnknown; - } - } -} - static void furi_hal_version_set_name(const char* name) { if(name != NULL) { strlcpy(furi_hal_version.name, name, FURI_HAL_VERSION_ARRAY_NAME_LENGTH); @@ -124,8 +129,6 @@ static void furi_hal_version_load_otp_v0() { furi_hal_version.board_target = otp->board_target; furi_hal_version.board_body = otp->board_body; furi_hal_version.board_connect = otp->board_connect; - furi_hal_version.board_color = 0; - furi_hal_version.board_region = 0; furi_hal_version_set_name(otp->name); } @@ -144,9 +147,33 @@ static void furi_hal_version_load_otp_v1() { furi_hal_version_set_name(otp->name); } +static void furi_hal_version_load_otp_v2() { + const FuriHalVersionOTPv2* otp = (FuriHalVersionOTPv2*)FURI_HAL_VERSION_OTP_ADDRESS; + + // 1st block, programmed afer baking + furi_hal_version.timestamp = otp->header_timestamp; + + // 2nd block, programmed afer baking + furi_hal_version.board_version = otp->board_version; + furi_hal_version.board_target = otp->board_target; + furi_hal_version.board_body = otp->board_body; + furi_hal_version.board_connect = otp->board_connect; + furi_hal_version.board_display = otp->board_display; + + // 3rd and 4th blocks, programmed on FATP stage + if (otp->board_color != 0xFF) { + furi_hal_version.board_color = otp->board_color; + furi_hal_version.board_region = otp->board_region; + furi_hal_version_set_name(otp->name); + } else { + furi_hal_version.board_color = 0; + furi_hal_version.board_region = 0; + furi_hal_version_set_name(NULL); + } +} + void furi_hal_version_init() { - furi_hal_version.otp_version = furi_hal_version_get_otp_version(); - switch(furi_hal_version.otp_version) { + switch(furi_hal_version_get_otp_version()) { case FuriHalVersionOtpVersionUnknown: furi_hal_version_load_otp_default(); break; @@ -159,6 +186,9 @@ void furi_hal_version_init() { case FuriHalVersionOtpVersion1: furi_hal_version_load_otp_v1(); break; + case FuriHalVersionOtpVersion2: + furi_hal_version_load_otp_v2(); + break; default: furi_crash(NULL); } FURI_LOG_I("FuriHalVersion", "Init OK"); @@ -172,6 +202,28 @@ const char* furi_hal_version_get_model_name() { return "Flipper Zero"; } +const FuriHalVersionOtpVersion furi_hal_version_get_otp_version() { + if (*(uint64_t*)FURI_HAL_VERSION_OTP_ADDRESS == 0xFFFFFFFF) { + return FuriHalVersionOtpVersionEmpty; + } else { + if (((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_magic == FURI_HAL_VERSION_OTP_HEADER_MAGIC) { + // Version 1+ + uint8_t version = ((FuriHalVersionOTPv1*)FURI_HAL_VERSION_OTP_ADDRESS)->header_version; + if (version >= FuriHalVersionOtpVersion1 && version <= FuriHalVersionOtpVersion2) { + return version; + } else { + return FuriHalVersionOtpVersionUnknown; + } + } else if (((FuriHalVersionOTPv0*)FURI_HAL_VERSION_OTP_ADDRESS)->board_version <= 10) { + // Version 0 + return FuriHalVersionOtpVersion0; + } else { + // Version Unknown + return FuriHalVersionOtpVersionUnknown; + } + } +} + const uint8_t furi_hal_version_get_hw_version() { return furi_hal_version.board_version; } @@ -196,6 +248,10 @@ const FuriHalVersionRegion furi_hal_version_get_hw_region() { return furi_hal_version.board_region; } +const FuriHalVersionDisplay furi_hal_version_get_hw_display() { + return furi_hal_version.board_display; +} + const uint32_t furi_hal_version_get_hw_timestamp() { return furi_hal_version.timestamp; } diff --git a/firmware/targets/furi-hal-include/furi-hal-version.h b/firmware/targets/furi-hal-include/furi-hal-version.h index ac28188e..00dc5cba 100644 --- a/firmware/targets/furi-hal-include/furi-hal-version.h +++ b/firmware/targets/furi-hal-include/furi-hal-version.h @@ -19,6 +19,15 @@ extern "C" { /** BLE symbol + "Flipper " + name */ #define FURI_HAL_VERSION_DEVICE_NAME_LENGTH (1 + 8 + FURI_HAL_VERSION_ARRAY_NAME_LENGTH) +/** OTP Versions enum */ +typedef enum { + FuriHalVersionOtpVersion0=0x00, + FuriHalVersionOtpVersion1=0x01, + FuriHalVersionOtpVersion2=0x02, + FuriHalVersionOtpVersionEmpty=0xFFFFFFFE, + FuriHalVersionOtpVersionUnknown=0xFFFFFFFF, +} FuriHalVersionOtpVersion; + /** Device Colors */ typedef enum { FuriHalVersionColorUnknown=0x00, @@ -34,6 +43,13 @@ typedef enum { FuriHalVersionRegionJp=0x03, } FuriHalVersionRegion; +/** Device Display */ +typedef enum { + FuriHalVersionDisplayUnknown=0x00, + FuriHalVersionDisplayErc=0x01, + FuriHalVersionDisplayMgg=0x02, +} FuriHalVersionDisplay; + /** Init flipper version */ void furi_hal_version_init(); @@ -50,6 +66,12 @@ bool furi_hal_version_do_i_belong_here(); */ const char* furi_hal_version_get_model_name(); +/** Get OTP version + * + * @return OTP Version + */ +const FuriHalVersionOtpVersion furi_hal_version_get_otp_version(); + /** Get hardware version * * @return Hardware Version @@ -86,6 +108,12 @@ const uint8_t furi_hal_version_get_hw_connect(); */ const FuriHalVersionRegion furi_hal_version_get_hw_region(); +/** Get hardware display id + * + * @return Display id + */ +const FuriHalVersionDisplay furi_hal_version_get_hw_display(); + /** Get hardware timestamp * * @return Hardware Manufacture timestamp diff --git a/scripts/otp.py b/scripts/otp.py index 4b42f636..029c3aca 100755 --- a/scripts/otp.py +++ b/scripts/otp.py @@ -10,7 +10,7 @@ import struct import datetime OTP_MAGIC = 0xBABE -OTP_VERSION = 0x01 +OTP_VERSION = 0x02 OTP_RESERVED = 0x00 OTP_COLORS = { @@ -18,6 +18,7 @@ OTP_COLORS = { "black": 0x01, "white": 0x02, } + OTP_REGIONS = { "unknown": 0x00, "eu_ru": 0x01, @@ -25,7 +26,11 @@ OTP_REGIONS = { "jp": 0x03, } -BOARD_RESERVED = 0x0000 +OTP_DISPLAYS = { + "unknown": 0x00, + "erc": 0x01, + "mgg": 0x02, +} class Main: @@ -34,22 +39,36 @@ class Main: self.parser = argparse.ArgumentParser() self.parser.add_argument("-d", "--debug", action="store_true", help="Debug") self.subparsers = self.parser.add_subparsers(help="sub-command help") - # Generate - self.parser_generate = self.subparsers.add_parser( + # Generate All + self.parser_generate_all = self.subparsers.add_parser( "generate", help="Generate OTP binary" ) - self._add_args(self.parser_generate) - self.parser_generate.add_argument("file", help="Output file") - self.parser_generate.set_defaults(func=self.generate) - # Flash - self.parser_flash = self.subparsers.add_parser( - "flash", help="Flash OTP to device" + self._add_first_args(self.parser_generate_all) + self._add_second_args(self.parser_generate_all) + self.parser_generate_all.add_argument("file", help="Output file") + self.parser_generate_all.set_defaults(func=self.generate_all) + # Flash First + self.parser_flash_first = self.subparsers.add_parser( + "flash_first", help="Flash first block of OTP to device" ) - self._add_args(self.parser_flash) - self.parser_flash.add_argument( - "--port", type=str, help="Port to connect: swd or usb1", default="swd" + self._add_swd_args(self.parser_flash_first) + self._add_first_args(self.parser_flash_first) + self.parser_flash_first.set_defaults(func=self.flash_first) + # Flash Second + self.parser_flash_second = self.subparsers.add_parser( + "flash_second", help="Flash second block of OTP to device" ) - self.parser_flash.set_defaults(func=self.flash) + self._add_swd_args(self.parser_flash_second) + self._add_second_args(self.parser_flash_second) + self.parser_flash_second.set_defaults(func=self.flash_second) + # Flash All + self.parser_flash_all = self.subparsers.add_parser( + "flash_all", help="Flash OTP to device" + ) + self._add_swd_args(self.parser_flash_all) + self._add_first_args(self.parser_flash_all) + self._add_second_args(self.parser_flash_all) + self.parser_flash_all.set_defaults(func=self.flash_all) # logging self.logger = logging.getLogger() self.timestamp = datetime.datetime.now().timestamp() @@ -69,16 +88,29 @@ class Main: # execute requested function self.args.func() - def _add_args(self, parser): - parser.add_argument("--version", type=int, help="Version", default=11) - parser.add_argument("--firmware", type=int, help="Firmware", default=7) - parser.add_argument("--body", type=int, help="Body", default=9) - parser.add_argument("--connect", type=int, help="Connect", default=6) - parser.add_argument("--color", type=str, help="Color", default="unknown") - parser.add_argument("--region", type=str, help="Region", default="unknown") + def _add_swd_args(self, parser): + parser.add_argument( + "--port", type=str, help="Port to connect: swd or usb1", default="swd" + ) + + def _add_first_args(self, parser): + parser.add_argument("--version", type=int, help="Version", required=True) + parser.add_argument("--firmware", type=int, help="Firmware", required=True) + parser.add_argument("--body", type=int, help="Body", required=True) + parser.add_argument("--connect", type=int, help="Connect", required=True) + parser.add_argument("--display", type=str, help="Display", required=True) + + def _add_second_args(self, parser): + parser.add_argument("--color", type=str, help="Color", required=True) + parser.add_argument("--region", type=str, help="Region", required=True) parser.add_argument("--name", type=str, help="Name", required=True) - def _process_args(self): + def _process_first_args(self): + if self.args.display not in OTP_DISPLAYS: + self.parser.error(f"Invalid display. Use one of {OTP_DISPLAYS.keys()}") + self.args.display = OTP_DISPLAYS[self.args.display] + + def _process_second_args(self): if self.args.color not in OTP_COLORS: self.parser.error(f"Invalid color. Use one of {OTP_COLORS.keys()}") self.args.color = OTP_COLORS[self.args.color] @@ -94,9 +126,9 @@ class Main: "Name contains incorrect symbols. Only a-zA-Z0-9 allowed." ) - def _pack_struct(self): + def _pack_first(self): return struct.pack( - "<" "HBBL" "BBBBBBH" "8s", + "<" "HBBL" "BBBBBBH", OTP_MAGIC, OTP_VERSION, OTP_RESERVED, @@ -105,25 +137,74 @@ class Main: self.args.firmware, self.args.body, self.args.connect, + self.args.display, + OTP_RESERVED, + OTP_RESERVED, + ) + + def _pack_second(self): + return struct.pack( + "<" "BBHL" "8s", self.args.color, self.args.region, - BOARD_RESERVED, + OTP_RESERVED, + OTP_RESERVED, self.args.name.encode("ascii"), ) - def generate(self): + def generate_all(self): self.logger.debug(f"Generating OTP") - self._process_args() - data = self._pack_struct() - open(self.args.file, "wb").write(data) + self._process_first_args() + self._process_second_args() + open(f"{self.args.file}_first.bin", "wb").write(self._pack_first()) + open(f"{self.args.file}_second.bin", "wb").write(self._pack_second()) - def flash(self): + def flash_first(self): + self.logger.debug(f"Flashing first block of OTP") + + self._process_first_args() + + filename = f"otp_unknown_first_{self.timestamp}.bin" + file = open(filename, "wb") + file.write(self._pack_first()) + file.close() + + self._flash_bin("0x1FFF7000", filename) + + os.remove(filename) + + def flash_second(self): + self.logger.debug(f"Flashing second block of OTP") + + self._process_second_args() + + filename = f"otp_{self.args.name}_second_{self.timestamp}.bin" + file = open(filename, "wb") + file.write(self._pack_second()) + file.close() + + self._flash_bin("0x1FFF7010", filename) + + os.remove(filename) + + def flash_all(self): self.logger.debug(f"Flashing OTP") - self._process_args() - data = self._pack_struct() - filename = f"otp_{self.args.name}_{self.timestamp}.bin" - open(filename, "wb").write(data) + self._process_first_args() + self._process_second_args() + + filename = f"otp_{self.args.name}_whole_{self.timestamp}.bin" + file = open(filename, "wb") + file.write(self._pack_first()) + file.write(self._pack_second()) + file.close() + + self._flash_bin("0x1FFF7000", filename) + + os.remove(filename) + + def _flash_bin(self, address, filename): + self.logger.debug(f"Programming {filename} at {address}") try: output = subprocess.check_output( [ @@ -133,7 +214,7 @@ class Main: f"port={self.args.port}", "-d", filename, - "0x1FFF7000", + f"{address}", ] ) assert output @@ -155,7 +236,6 @@ class Main: f"port={self.args.port}", ] ) - os.remove(filename) if __name__ == "__main__":