flash/nor/kinetis: fix FCF handling
Kinetis Flash Configuration Field needs special handling to prevent unwanted locking of the device. Warn user about any difference between generated FCF and FCF data in the programmed file. Inform user that re-programming of already programmed FCF may fail on devices with FTFE flash module. While on it remove useless setting of is_erased flag after erase. Change-Id: I3911f436674547fa12ef3886c7d5e8cd889f9e2b Signed-off-by: Tomas Vanek <vanekt@fbl.cz> Fixes: https://sourceforge.net/p/openocd/tickets/270/ Reported-by: Noel Diviney <vk3avm@users.sourceforge.net> Reviewed-on: http://openocd.zylin.com/5753 Tested-by: jenkins
This commit is contained in:
parent
8d7ca43775
commit
fd9a7a8c8a
|
@ -389,7 +389,6 @@ static const struct kinetis_type kinetis_types_old[] = {
|
||||||
|
|
||||||
static bool allow_fcf_writes;
|
static bool allow_fcf_writes;
|
||||||
static uint8_t fcf_fopt = 0xff;
|
static uint8_t fcf_fopt = 0xff;
|
||||||
static bool fcf_fopt_configured;
|
|
||||||
static bool create_banks;
|
static bool create_banks;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1650,8 +1649,6 @@ static int kinetis_erase(struct flash_bank *bank, unsigned int first,
|
||||||
return ERROR_FLASH_OPERATION_FAILED;
|
return ERROR_FLASH_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bank->sectors[i].is_erased = 1;
|
|
||||||
|
|
||||||
if (k_bank->prog_base == 0
|
if (k_bank->prog_base == 0
|
||||||
&& bank->sectors[i].offset <= FCF_ADDRESS
|
&& bank->sectors[i].offset <= FCF_ADDRESS
|
||||||
&& bank->sectors[i].offset + bank->sectors[i].size > FCF_ADDRESS + FCF_SIZE) {
|
&& bank->sectors[i].offset + bank->sectors[i].size > FCF_ADDRESS + FCF_SIZE) {
|
||||||
|
@ -1665,7 +1662,8 @@ static int kinetis_erase(struct flash_bank *bank, unsigned int first,
|
||||||
result = kinetis_write_inner(bank, fcf_buffer, FCF_ADDRESS, FCF_SIZE);
|
result = kinetis_write_inner(bank, fcf_buffer, FCF_ADDRESS, FCF_SIZE);
|
||||||
if (result != ERROR_OK)
|
if (result != ERROR_OK)
|
||||||
LOG_WARNING("Flash Configuration Field write failed");
|
LOG_WARNING("Flash Configuration Field write failed");
|
||||||
bank->sectors[i].is_erased = 0;
|
else
|
||||||
|
LOG_DEBUG("Generated FCF written");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1909,6 +1907,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
int result;
|
int result;
|
||||||
bool set_fcf = false;
|
bool set_fcf = false;
|
||||||
bool fcf_in_data_valid = false;
|
bool fcf_in_data_valid = false;
|
||||||
|
bool fcf_differs = false;
|
||||||
int sect = 0;
|
int sect = 0;
|
||||||
struct kinetis_flash_bank *k_bank = bank->driver_priv;
|
struct kinetis_flash_bank *k_bank = bank->driver_priv;
|
||||||
struct kinetis_chip *k_chip = k_bank->k_chip;
|
struct kinetis_chip *k_chip = k_bank->k_chip;
|
||||||
|
@ -1941,31 +1940,45 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
&& offset + count >= FCF_ADDRESS + FCF_SIZE;
|
&& offset + count >= FCF_ADDRESS + FCF_SIZE;
|
||||||
if (fcf_in_data_valid) {
|
if (fcf_in_data_valid) {
|
||||||
memcpy(fcf_in_data, buffer + FCF_ADDRESS - offset, FCF_SIZE);
|
memcpy(fcf_in_data, buffer + FCF_ADDRESS - offset, FCF_SIZE);
|
||||||
if (memcmp(fcf_in_data + FCF_FPROT, fcf_buffer, 4)) {
|
if (memcmp(fcf_in_data, fcf_buffer, 8)) {
|
||||||
fcf_in_data_valid = false;
|
fcf_differs = true;
|
||||||
LOG_INFO("Flash protection requested in programmed file differs from current setting.");
|
LOG_INFO("Setting of backdoor key is not supported in mode 'kinetis fcf_source protection'.");
|
||||||
|
}
|
||||||
|
if (memcmp(fcf_in_data + FCF_FPROT, fcf_buffer + FCF_FPROT, 4)) {
|
||||||
|
fcf_differs = true;
|
||||||
|
LOG_INFO("Flash protection requested in the programmed file differs from current setting.");
|
||||||
}
|
}
|
||||||
if (fcf_in_data[FCF_FDPROT] != fcf_buffer[FCF_FDPROT]) {
|
if (fcf_in_data[FCF_FDPROT] != fcf_buffer[FCF_FDPROT]) {
|
||||||
fcf_in_data_valid = false;
|
fcf_differs = true;
|
||||||
LOG_INFO("Data flash protection requested in programmed file differs from current setting.");
|
LOG_INFO("Data flash protection requested in the programmed file differs from current setting.");
|
||||||
}
|
}
|
||||||
if ((fcf_in_data[FCF_FSEC] & 3) != 2) {
|
if ((fcf_in_data[FCF_FSEC] & 3) != 2) {
|
||||||
fcf_in_data_valid = false;
|
fcf_in_data_valid = false;
|
||||||
LOG_INFO("Device security requested in programmed file!");
|
LOG_INFO("Device security requested in the programmed file! Write denied.");
|
||||||
} else if (k_chip->flash_support & FS_ECC
|
} else if (fcf_in_data[FCF_FSEC] != fcf_buffer[FCF_FSEC]) {
|
||||||
&& fcf_in_data[FCF_FSEC] != fcf_buffer[FCF_FSEC]) {
|
fcf_differs = true;
|
||||||
fcf_in_data_valid = false;
|
|
||||||
LOG_INFO("Strange unsecure mode 0x%02" PRIx8
|
LOG_INFO("Strange unsecure mode 0x%02" PRIx8
|
||||||
"requested in programmed file!",
|
" requested in the programmed file, set FSEC = 0x%02" PRIx8
|
||||||
fcf_in_data[FCF_FSEC]);
|
" in the startup code!",
|
||||||
|
fcf_in_data[FCF_FSEC], fcf_buffer[FCF_FSEC]);
|
||||||
}
|
}
|
||||||
if ((k_chip->flash_support & FS_ECC || fcf_fopt_configured)
|
if (fcf_in_data[FCF_FOPT] != fcf_buffer[FCF_FOPT]) {
|
||||||
&& fcf_in_data[FCF_FOPT] != fcf_fopt) {
|
fcf_differs = true;
|
||||||
fcf_in_data_valid = false;
|
LOG_INFO("FOPT requested in the programmed file differs from current setting, set 'kinetis fopt 0x%02"
|
||||||
LOG_INFO("FOPT requested in programmed file differs from current setting.");
|
PRIx8 "'.", fcf_in_data[FCF_FOPT]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the device has ECC flash, then we cannot re-program FCF */
|
||||||
|
if (fcf_differs) {
|
||||||
|
if (k_chip->flash_support & FS_ECC) {
|
||||||
|
fcf_in_data_valid = false;
|
||||||
|
LOG_INFO("Cannot re-program FCF. Expect verify errors at FCF (0x400-0x40f).");
|
||||||
|
} else {
|
||||||
|
LOG_INFO("Trying to re-program FCF.");
|
||||||
|
if (!(k_chip->flash_support & FS_PROGRAM_LONGWORD))
|
||||||
|
LOG_INFO("Flash re-programming may fail on this device!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!fcf_in_data_valid)
|
|
||||||
LOG_INFO("Expect verify errors at FCF (0x408-0x40f).");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3035,7 +3048,6 @@ COMMAND_HANDLER(kinetis_fopt_handler)
|
||||||
|
|
||||||
if (CMD_ARGC == 1) {
|
if (CMD_ARGC == 1) {
|
||||||
fcf_fopt = (uint8_t)strtoul(CMD_ARGV[0], NULL, 0);
|
fcf_fopt = (uint8_t)strtoul(CMD_ARGV[0], NULL, 0);
|
||||||
fcf_fopt_configured = true;
|
|
||||||
} else {
|
} else {
|
||||||
command_print(CMD, "FCF_FOPT 0x%02" PRIx8, fcf_fopt);
|
command_print(CMD, "FCF_FOPT 0x%02" PRIx8, fcf_fopt);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue