diff --git a/core/Makefile b/core/Makefile index 1e2f124b2..7b86b5140 100644 --- a/core/Makefile +++ b/core/Makefile @@ -11,6 +11,7 @@ MAKE = make -j $(JOBS) SCONS = scons -Q -j $(JOBS) BUILD_DIR = build +PREPARE_BUILD_DIR = $(BUILD_DIR)/prepare BOARDLOADER_BUILD_DIR = $(BUILD_DIR)/boardloader BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/bootloader BOOTLOADER_CI_BUILD_DIR = $(BUILD_DIR)/bootloader_ci @@ -229,6 +230,10 @@ build: build_boardloader build_bootloader build_firmware build_prodtest build_un build_embed: build_boardloader build_bootloader build_firmware # build boardloader, bootloader, firmware +build_prepare: ## build prepare + $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \ + CMAKELISTS="$(CMAKELISTS)" $(PREPARE_BUILD_DIR)/prepare.bin + build_boardloader: ## build boardloader $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \ CMAKELISTS="$(CMAKELISTS)" $(BOARDLOADER_BUILD_DIR)/boardloader.bin @@ -283,9 +288,12 @@ build_cross: ## build mpy-cross port ## clean commands: -clean: clean_boardloader clean_bootloader clean_bootloader_emu clean_bootloader_ci clean_prodtest clean_reflash clean_firmware clean_unix clean_cross ## clean all +clean: clean_prepare clean_boardloader clean_bootloader clean_bootloader_emu clean_bootloader_ci clean_prodtest clean_reflash clean_firmware clean_unix clean_cross ## clean all rm -f ".sconsign.dblite" +clean_prepare: ## clean prepare build + rm -rf $(PREPARE_BUILD_DIR) + clean_boardloader: ## clean boardloader build rm -rf $(BOARDLOADER_BUILD_DIR) @@ -317,6 +325,9 @@ clean_cross: ## clean mpy-cross build flash: flash_boardloader flash_bootloader flash_firmware ## flash everything using OpenOCD +flash_prepare: $(PREPARE_BUILD_DIR)/prepare.bin ## flash prepare using OpenOCD + $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(FLASH_START); exit" + flash_boardloader: $(BOARDLOADER_BUILD_DIR)/boardloader.bin ## flash boardloader using OpenOCD $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(BOARDLOADER_START); exit" @@ -416,6 +427,8 @@ sizecheck: ## check sizes of binary files test $(FIRMWARE_P2_MAXSIZE) -ge $(shell wc -c < $(FIRMWARE_BUILD_DIR)/firmware.bin.p2) test $(FIRMWARE_MAXSIZE) -ge $(shell wc -c < $(FIRMWARE_BUILD_DIR)/firmware.bin) + +ifeq ($(MCU),$(filter $(MCU),STM32F4)) combine: ## combine boardloader + bootloader + prodtest into one combined image ./tools/combine_firmware \ $(LAYOUT_FILE) \ @@ -423,8 +436,6 @@ combine: ## combine boardloader + bootloader + prodtest into one combined image -b BOARDLOADER $(BOARDLOADER_BUILD_DIR)/boardloader.bin \ -b BOOTLOADER $(BOOTLOADER_BUILD_DIR)/bootloader.bin \ -b FIRMWARE $(PRODTEST_BUILD_DIR)/prodtest.bin - -ifeq ($(MCU),$(filter $(MCU),STM32F4)) combine_fw: ## combine boardloader + bootloader + firmware into one combined image ./tools/combine_firmware \ $(LAYOUT_FILE) \ @@ -434,10 +445,19 @@ combine_fw: ## combine boardloader + bootloader + firmware into one combined ima -b FIRMWARE $(FIRMWARE_BUILD_DIR)/firmware.bin.p1 \ -b FIRMWARE_P2 $(FIRMWARE_BUILD_DIR)/firmware.bin.p2 else ifeq ($(MCU),$(filter $(MCU),STM32U5)) +combine: ## combine boardloader + bootloader + prodtest into one combined image + ./tools/combine_firmware \ + $(LAYOUT_FILE) \ + $(PRODTEST_BUILD_DIR)/combined.bin \ + -b FLASH $(PREPARE_BUILD_DIR)/prepare.bin \ + -b BOARDLOADER $(BOARDLOADER_BUILD_DIR)/boardloader.bin \ + -b BOOTLOADER $(BOOTLOADER_BUILD_DIR)/bootloader.bin \ + -b FIRMWARE $(PRODTEST_BUILD_DIR)/prodtest.bin combine_fw: ## combine boardloader + bootloader + firmware into one combined image ./tools/combine_firmware \ $(LAYOUT_FILE) \ $(PRODTEST_BUILD_DIR)/combined.bin \ + -b FLASH $(PREPARE_BUILD_DIR)/prepare.bin \ -b BOARDLOADER $(BOARDLOADER_BUILD_DIR)/boardloader.bin \ -b BOOTLOADER $(BOOTLOADER_BUILD_DIR)/bootloader.bin \ -b FIRMWARE $(FIRMWARE_BUILD_DIR)/firmware.bin diff --git a/core/SConscript.prepare b/core/SConscript.prepare new file mode 100644 index 000000000..57092ef49 --- /dev/null +++ b/core/SConscript.prepare @@ -0,0 +1,144 @@ +# pylint: disable=E0602 + +import os +import tools + +TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') +CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) + +if TREZOR_MODEL not in ('T3T1', ): + # skip prepare build + env = Environment() + def build_prepare(target,source,env): + print(f'Prepare: nothing to build for Model {TREZOR_MODEL}') + program_bin = env.Command( + target='prepare.bin', + source=None, + action=build_prepare + ) + Return() + +FEATURES_WANTED = [] + +CCFLAGS_MOD = '' +CPPPATH_MOD = [] +CPPDEFINES_MOD = ["PREPARE"] +SOURCE_MOD = [] +CPPDEFINES_HAL = [] +SOURCE_HAL = [] +PATH_HAL = [] + +CPPPATH_MOD += [ + 'vendor/trezor-crypto', + 'vendor/trezor-storage', +] + +CCFLAGS_MOD += '-Wno-sequence-point ' + + +env = Environment(ENV=os.environ, + CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0')), + CONSTRAINTS=[], + CPPDEFINES_IMPLICIT=[] + ) + +FEATURES_AVAILABLE = tools.configure_board(TREZOR_MODEL, FEATURES_WANTED, env, CPPDEFINES_HAL, SOURCE_HAL, PATH_HAL) + +FILE_SUFFIX= env.get('ENV')['SUFFIX'] +LINKER_SCRIPT_SUFFIX= env.get('ENV')['LINKER_SCRIPT'] + +SOURCE_PREPARE = [ + f"embed/prepare/startup_{FILE_SUFFIX}.s", + 'embed/prepare/main.c', + 'embed/lib/terminal.c', + 'embed/lib/fonts/font_bitmap.c', + 'embed/lib/mini_printf.c', +] + +env.Replace( + CP='cp', + AS='arm-none-eabi-as', + AR='arm-none-eabi-ar', + CC='arm-none-eabi-gcc', + LINK='arm-none-eabi-gcc', + SIZE='arm-none-eabi-size', + STRIP='arm-none-eabi-strip', + OBJCOPY='arm-none-eabi-objcopy', + PYTHON='python', + MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py',) + +env.Replace( + TREZOR_MODEL=TREZOR_MODEL, ) + +env.Replace( + COPT=env.get('ENV').get('OPTIMIZE', '-Os'), + CCFLAGS='$COPT ' + '-g3 ' + '-nostdlib ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -fno-common ' + '-fsingle-precision-constant -fdata-sections -ffunction-sections ' + '-ffreestanding ' + '-fstack-protector-all ' + + env.get('ENV')["CPU_CCFLAGS"] + CCFLAGS_MOD, + CCFLAGS_QSTR='-DNO_QSTR -DN_X64 -DN_X86 -DN_THUMB', + LINKFLAGS=f"-T embed/prepare/memory_{LINKER_SCRIPT_SUFFIX}.ld -Wl,--gc-sections -Wl,-Map=build/prepare/prepare.map -Wl,--warn-common -Wl,--print-memory-usage", + CPPPATH=[ + 'embed/prepare', + 'embed/lib', + 'embed/models', + 'embed/trezorhal', + 'embed/extmod/modtrezorui', + 'vendor/micropython/lib/cmsis/inc', + ] + CPPPATH_MOD + PATH_HAL, + CPPDEFINES=[ + 'PREPARE', + 'TREZOR_MODEL_'+TREZOR_MODEL, + 'USE_HAL_DRIVER', + ] + CPPDEFINES_MOD + CPPDEFINES_HAL, + ASFLAGS=env.get('ENV')['CPU_ASFLAGS'], + ASPPFLAGS='$CFLAGS $CCFLAGS', + ) + +env.Replace( + ALLSOURCES=SOURCE_MOD + SOURCE_PREPARE + SOURCE_HAL, + ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES'] + env['CPPDEFINES_IMPLICIT'])) + +cmake_gen = env.Command( + target='CMakeLists.txt', + source='', + action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', +) + +# +# Program objects +# + +obj_program = [] +obj_program += env.Object(source=SOURCE_MOD) +obj_program += env.Object(source=SOURCE_PREPARE) +obj_program += env.Object(source=SOURCE_HAL) + +program_elf = env.Command( + target='prepare.elf', + source=obj_program, + action= + '$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES -lc_nano -lgcc', +) + +BINARY_NAME = f"build/prepare/prepare-{tools.get_model_identifier(TREZOR_MODEL)}" +BINARY_NAME += "-" + tools.get_version('embed/prepare/version.h') +BINARY_NAME += "-" + tools.get_git_revision_short_hash() +BINARY_NAME += "-dirty" if tools.get_git_modified() else "" +BINARY_NAME += ".bin" + +if CMAKELISTS != 0: + env.Depends(program_elf, cmake_gen) + +program_bin = env.Command( + target='prepare.bin', + source=program_elf, + action=[ + '$OBJCOPY -O binary -j .vector_table -j .text -j .data -j .rodata -j .capabilities -j .sensitive $SOURCE $TARGET', + '$CP $TARGET ' + BINARY_NAME, + ], +) diff --git a/core/SConstruct b/core/SConstruct index d4c5aae45..8a7c13ffd 100644 --- a/core/SConstruct +++ b/core/SConstruct @@ -9,5 +9,6 @@ SConscript('SConscript.bootloader_ci', variant_dir='build/bootloader_ci', duplic SConscript('SConscript.bootloader_emu', variant_dir='build/bootloader_emu', duplicate=False) SConscript('SConscript.firmware', variant_dir='build/firmware', duplicate=False) SConscript('SConscript.prodtest', variant_dir='build/prodtest', duplicate=False) +SConscript('SConscript.prepare', variant_dir='build/prepare', duplicate=False) SConscript('SConscript.reflash', variant_dir='build/reflash', duplicate=False) SConscript('SConscript.unix', variant_dir='build/unix', duplicate=False) diff --git a/core/embed/prepare/main.c b/core/embed/prepare/main.c new file mode 100644 index 000000000..3f704f523 --- /dev/null +++ b/core/embed/prepare/main.c @@ -0,0 +1,34 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include TREZOR_BOARD +#include "lowlevel.h" + +int main(void) { + // need the systick timer running before many HAL operations. + // want the PVD enabled before flash operations too. + periph_init(); + + if (sectrue != flash_configure_basic_option_bytes()) { + NVIC_SystemReset(); + return 2; + } + + return 0; +} diff --git a/core/embed/prepare/memory_stm32u58.ld b/core/embed/prepare/memory_stm32u58.ld new file mode 100644 index 000000000..157772dbf --- /dev/null +++ b/core/embed/prepare/memory_stm32u58.ld @@ -0,0 +1,109 @@ +/* Trezor v2 boardloader linker script */ + +ENTRY(reset_handler) + +MEMORY { + FLASH (rx) : ORIGIN = 0x0C000000, LENGTH = 16K + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 192K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x3002FF00, LENGTH = 0x100 + SRAM2 (wal) : ORIGIN = 0x30030000, LENGTH = 64K + SRAM3 (wal) : ORIGIN = 0x30040000, LENGTH = 512K + SRAM5 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM5 is not available */ + SRAM6 (wal) : ORIGIN = 0x30080000, LENGTH = 0K /* SRAM6 is not available */ + SRAM4 (wal) : ORIGIN = 0x38000000, LENGTH = 16K +} + +main_stack_base = ORIGIN(SRAM2) + SIZEOF(.stack); /* 8-byte aligned full descending stack */ +_sstack = ORIGIN(SRAM2); +_estack = main_stack_base; + +/* used by the startup code to populate variables used by the C code */ +data_lma = LOADADDR(.data); +data_vma = ADDR(.data); +data_size = SIZEOF(.data); + +/* used by the startup code to populate variables used by the C code */ +sensitive_lma = LOADADDR(.sensitive); +sensitive_vma = ADDR(.sensitive); +sensitive_size = SIZEOF(.sensitive); + +/* used by the startup code to wipe memory */ +sram1_start = ORIGIN(SRAM1); +sram1_end = ORIGIN(SRAM1) + LENGTH(SRAM1); +sram2_start = ORIGIN(SRAM2); +sram2_end = ORIGIN(SRAM2) + LENGTH(SRAM2); +sram3_start = ORIGIN(SRAM3); +sram3_end = ORIGIN(SRAM3) + LENGTH(SRAM3); +sram4_start = ORIGIN(SRAM4); +sram4_end = ORIGIN(SRAM4) + LENGTH(SRAM4); +sram5_start = ORIGIN(SRAM5); +sram5_end = ORIGIN(SRAM5) + LENGTH(SRAM5); +sram6_start = ORIGIN(SRAM6); +sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); + +/* reserve 256 bytes for bootloader arguments */ +boot_args_start = ORIGIN(BOOT_ARGS); +boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); + +SECTIONS { + .vector_table : ALIGN(512) { + KEEP(*(.vector_table)); + } >FLASH AT>FLASH + + .text : ALIGN(4) { + *(.text*); + . = ALIGN(4); /* make the section size a multiple of the word size */ + } >FLASH AT>FLASH + + .rodata : ALIGN(4) { + *(.rodata*); + . = ALIGN(4); /* make the section size a multiple of the word size */ + } >FLASH AT>FLASH + + .data : ALIGN(4) { + *(.data*); + . = ALIGN(8); + } >SRAM1 AT>FLASH + + /DISCARD/ : { + *(.ARM.exidx*); + } + + .bss : ALIGN(4) { + *(.bss*); + . = ALIGN(4); + } >SRAM1 + + .buf : ALIGN(4) { + *(.buf*); + . = ALIGN(4); + } >SRAM1 + + .stack : ALIGN(8) { + . = 16K; /* Overflow causes UsageFault */ + } >SRAM2 + + .sensitive : ALIGN(8) { + *(.sensitive*); + . = ALIGN(4); + } >SRAM2 AT>FLASH + + .fb : ALIGN(4) { + __fb_start = .; + *(.fb1*); + *(.fb2*); + __fb_end = .; + . = ALIGN(4); + } >SRAM3 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS + + + /* Hard-coded address for capabilities structure */ + .capabilities 0x0C00FF00 : {KEEP(*(.capabilities_section))} +} diff --git a/core/embed/prepare/startup_stm32u5.s b/core/embed/prepare/startup_stm32u5.s new file mode 100644 index 000000000..991af48e5 --- /dev/null +++ b/core/embed/prepare/startup_stm32u5.s @@ -0,0 +1,107 @@ + .syntax unified + + .text + + .global reset_handler + .type reset_handler, STT_FUNC +reset_handler: + // set the stack protection + ldr r0, =_sstack + add r0, r0, #16 // padding + msr MSPLIM, r0 + + bl SystemInit + + // read the first rng data and save it + ldr r0, =0 // r0 - previous value + ldr r1, =0 // r1 - whether to compare the previous value + bl rng_read + + // read the next rng data and make sure it is different than previous + // r0 - value returned from previous call + ldr r1, =1 // r1 - whether to compare the previous value + bl rng_read + mov r4, r0 // save TRNG output in r4 + + // wipe memory to remove any possible vestiges of sensitive data + + +fill_ram: + ldr r0, =sram1_start // r0 - point to beginning of SRAM + ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + mov r2, r4 // r2 - the word-sized value to be written + bl memset_reg + + ldr r0, =sram2_start // r0 - point to beginning of SRAM + ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + mov r2, r4 // r2 - the word-sized value to be written + bl memset_reg + + ldr r0, =sram3_start // r0 - point to beginning of SRAM + ldr r1, =sram3_end // r1 - point to byte after the end of SRAM + mov r2, r4 // r2 - the word-sized value to be written + bl memset_reg + + ldr r0, =sram4_start // r0 - point to beginning of SRAM + ldr r1, =sram4_end // r1 - point to byte after the end of SRAM + mov r2, r4 // r2 - the word-sized value to be written + bl memset_reg + + ldr r0, =sram5_start // r0 - point to beginning of SRAM + ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + mov r2, r4 // r2 - the word-sized value to be written + bl memset_reg + + ldr r0, =sram6_start // r0 - point to beginning of SRAM + ldr r1, =sram6_end // r1 - point to byte after the end of SRAM + mov r2, r4 // r2 - the word-sized value to be written + bl memset_reg + + + // setup environment for subsequent stage of code + + +clear_ram: + ldr r2, =0 // r2 - the word-sized value to be written + ldr r0, =sram1_start // r0 - point to beginning of SRAM + ldr r1, =sram1_end // r1 - point to byte after the end of SRAM + bl memset_reg + ldr r0, =sram2_start // r0 - point to beginning of SRAM + ldr r1, =sram2_end // r1 - point to byte after the end of SRAM + bl memset_reg + ldr r0, =sram3_start // r0 - point to beginning of SRAM + ldr r1, =sram3_end // r1 - point to byte after the end of SRAM + bl memset_reg + ldr r0, =sram4_start // r0 - point to beginning of SRAM + ldr r1, =sram4_end // r1 - point to byte after the end of SRAM + bl memset_reg + ldr r0, =sram5_start // r0 - point to beginning of SRAM + ldr r1, =sram5_end // r1 - point to byte after the end of SRAM + bl memset_reg + ldr r0, =sram6_start // r0 - point to beginning of SRAM + ldr r1, =sram6_end // r1 - point to byte after the end of SRAM + bl memset_reg + + // copy data in from flash + ldr r0, =data_vma // dst addr + ldr r1, =data_lma // src addr + ldr r2, =data_size // size in bytes + bl memcpy + + // copy sensitive data in from flash + ldr r0, =sensitive_vma // dst addr + ldr r1, =sensitive_lma // src addr + ldr r2, =sensitive_size // size in bytes + bl memcpy + + // setup the stack protector (see build script "-fstack-protector-all") with an unpredictable value + bl rng_get + ldr r1, = __stack_chk_guard + str r0, [r1] + + // enter the application code + bl main + + b shutdown_privileged + + .end diff --git a/core/embed/prepare/version.h b/core/embed/prepare/version.h new file mode 100644 index 000000000..aca7ff091 --- /dev/null +++ b/core/embed/prepare/version.h @@ -0,0 +1,4 @@ +#define VERSION_MAJOR 0 +#define VERSION_MINOR 0 +#define VERSION_PATCH 1 +#define VERSION_BUILD 0 diff --git a/core/embed/trezorhal/lowlevel.h b/core/embed/trezorhal/lowlevel.h index 49757aeac..373f6359a 100644 --- a/core/embed/trezorhal/lowlevel.h +++ b/core/embed/trezorhal/lowlevel.h @@ -26,6 +26,7 @@ secbool flash_check_option_bytes(void); void flash_lock_option_bytes(void); void flash_unlock_option_bytes(void); uint32_t flash_set_option_bytes(void); +secbool flash_configure_basic_option_bytes(void); secbool flash_configure_option_bytes(void); void periph_init(void); secbool reset_flags_check(void); diff --git a/core/embed/trezorhal/stm32u5/lowlevel.c b/core/embed/trezorhal/stm32u5/lowlevel.c index a7f6463b3..221b2273c 100644 --- a/core/embed/trezorhal/stm32u5/lowlevel.c +++ b/core/embed/trezorhal/stm32u5/lowlevel.c @@ -170,6 +170,18 @@ secbool flash_check_option_bytes(void) { return sectrue; } +secbool flash_check_basic_option_bytes(void) { + flash_wait_and_clear_status_flags(); + + if ((FLASH->OPTR & FLASH_OPTR_TZEN) == 0) { + return secfalse; + } + if (FLASH->SECBOOTADD0R != FALSH_SECBOOTADD0R_VALUE) { + return secfalse; + } + return sectrue; +} + void flash_lock_option_bytes(void) { FLASH->NSCR |= FLASH_NSCR_OPTLOCK; // lock the option bytes } @@ -186,6 +198,37 @@ void flash_unlock_option_bytes(void) { ; // wait until the flash option control register is unlocked } +uint32_t flash_set_basic_option_bytes(void) { + if (flash_unlock_write() != sectrue) { + return 0; + } + flash_wait_and_clear_status_flags(); + flash_unlock_option_bytes(); + flash_wait_and_clear_status_flags(); + + FLASH->OPTR |= FLASH_OPTR_TZEN; + + FLASH->SECBOOTADD0R = FALSH_SECBOOTADD0R_VALUE; + + FLASH_WaitForLastOperation(HAL_MAX_DELAY); + + FLASH->NSCR |= FLASH_NSCR_OPTSTRT; + uint32_t result = + flash_wait_and_clear_status_flags(); // wait until changes are committed + + FLASH_WaitForLastOperation(HAL_MAX_DELAY); + + FLASH->NSCR |= FLASH_NSCR_OBL_LAUNCH; // begin committing changes to flash + result = + flash_wait_and_clear_status_flags(); // wait until changes are committed + flash_lock_option_bytes(); + + if (flash_lock_write() != sectrue) { + return 0; + } + return result; +} + uint32_t flash_set_option_bytes(void) { if (flash_unlock_write() != sectrue) { return 0; @@ -239,6 +282,18 @@ void check_oem_keys(void) { ensure(((FLASH->NSSR & FLASH_NSSR_OEM2LOCK) == 0) * sectrue, "OEM2 KEY SET"); } +secbool flash_configure_basic_option_bytes(void) { + if (sectrue == flash_check_basic_option_bytes()) { + return sectrue; // we DID NOT have to change the option bytes + } + + do { + flash_set_basic_option_bytes(); + + } while (sectrue != flash_check_basic_option_bytes()); + return secfalse; // notify that we DID have to change the option bytes +} + secbool flash_configure_option_bytes(void) { if (sectrue == flash_check_option_bytes()) { return sectrue; // we DID NOT have to change the option bytes