mirror of
https://github.com/smaeul/u-boot.git
synced 2025-10-14 04:46:01 +01:00
km: common: implement field fail-safe u-boot update
This patch provides possibility for field fail-safe u-boot updates. The implementation can be used on all pg-wcom boards that are booting from parallel NOR flash. When used in a board design, provided check_for_uboot_update function will start new u-boot at defined location if updateduboot envvar is set to yes. With this implementation it is expected that factory programmed u-boot will always stay as it is, and optionally new u-boot can be safely programmed by embedded software when the unit is rolled out on the field. It is expected check_for_uboot_update to be called early in execution before relocation (*_f) once SoC is basically initialized and environment can be read, with this possibilities to not be able to fix a u-boot bug by a u-boot update are reduced to minimum. Signed-off-by: Aleksandar Gerasimovski <aleksandar.gerasimovski@hitachienergy.com> Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
This commit is contained in:
parent
de144d5ffe
commit
efe19295a5
@ -130,6 +130,38 @@ config SYS_IVM_EEPROM_PAGE_LEN
|
|||||||
help
|
help
|
||||||
Page size of inventory in EEPROM.
|
Page size of inventory in EEPROM.
|
||||||
|
|
||||||
|
config PG_WCOM_UBOOT_UPDATE_SUPPORTED
|
||||||
|
bool "Enable U-boot Field Fail-Safe Update Functionality"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Indicates that field fail-safe u-boot update is supported.
|
||||||
|
This functionality works only for designs that are booting
|
||||||
|
from parallel NOR flash.
|
||||||
|
|
||||||
|
config PG_WCOM_UBOOT_BOOTPACKAGE
|
||||||
|
bool "U-boot Is Part Of Factory Boot-Package Image"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Indicates that u-boot will be a part of the factory programmed
|
||||||
|
boot-package image.
|
||||||
|
Has to be set for original u-boot programmed at factory.
|
||||||
|
|
||||||
|
config PG_WCOM_UBOOT_UPDATE_TEXT_BASE
|
||||||
|
hex "Text Base For U-boot Programmed Outside Factory"
|
||||||
|
default 0xFFFFFFFF
|
||||||
|
help
|
||||||
|
Text base of an updated u-boot that is not factory programmed but
|
||||||
|
later when the unit is rolled out on the field.
|
||||||
|
Has to be set for original u-boot programmed at factory.
|
||||||
|
|
||||||
|
config PG_WCOM_UBOOT_UPDATE
|
||||||
|
bool "U-boot Is Part Of Factory Boot-Package Image"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Indicates that u-boot will be a part of the embedded software and
|
||||||
|
programmed at field.
|
||||||
|
Has to be set for updated u-boot version programmed at field.
|
||||||
|
|
||||||
source "board/keymile/km83xx/Kconfig"
|
source "board/keymile/km83xx/Kconfig"
|
||||||
source "board/keymile/kmcent2/Kconfig"
|
source "board/keymile/kmcent2/Kconfig"
|
||||||
source "board/keymile/km_arm/Kconfig"
|
source "board/keymile/km_arm/Kconfig"
|
||||||
|
18
board/keymile/README
Normal file
18
board/keymile/README
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Field Fail-Save U-boot Update
|
||||||
|
-----------------------------
|
||||||
|
Field Fail-Save u-boot update is a feature that allows save u-boot update
|
||||||
|
of FOX and XMC products that are rolled out in the field.
|
||||||
|
|
||||||
|
The feature is initially implemented for designs based on LS102x SoC, but in
|
||||||
|
theory can be used on all designs that are booting from parallel NOR flash.
|
||||||
|
|
||||||
|
The implementation expects redundant (secondary) u-boot image on a predefined
|
||||||
|
location in the NOR flash, u-boot execution will be transferred to the redundant
|
||||||
|
(secondary) u-boot and redundant u-boot will be started if 'updateduboot' envvar
|
||||||
|
is set to 'yes'.
|
||||||
|
Update logic check_for_uboot_update() has to be invoked from the design early
|
||||||
|
before relocation just after SoC initialization, e.g from board_early_init_f or
|
||||||
|
misc_init_f functions.
|
||||||
|
By design it is expected that primary u-boot image is burned in the factory and
|
||||||
|
never updated, and in case u-boot update is required it can flashed and started
|
||||||
|
from secondary u-boot location.
|
@ -19,6 +19,8 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/bug.h>
|
||||||
|
#include <bootcount.h>
|
||||||
|
|
||||||
#if defined(CONFIG_POST)
|
#if defined(CONFIG_POST)
|
||||||
#include "post.h"
|
#include "post.h"
|
||||||
@ -76,6 +78,57 @@ int set_km_env(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(PG_WCOM_UBOOT_UPDATE_SUPPORTED)
|
||||||
|
#if ((!CONFIG_IS_ENABLED(PG_WCOM_UBOOT_BOOTPACKAGE) && \
|
||||||
|
!CONFIG_IS_ENABLED(PG_WCOM_UBOOT_UPDATE)) || \
|
||||||
|
(CONFIG_IS_ENABLED(PG_WCOM_UBOOT_BOOTPACKAGE) && \
|
||||||
|
CONFIG_IS_ENABLED(PG_WCOM_UBOOT_UPDATE)))
|
||||||
|
#error "It has to be either bootpackage or update u-boot image!"
|
||||||
|
#endif
|
||||||
|
void check_for_uboot_update(void)
|
||||||
|
{
|
||||||
|
void (*uboot_update_entry)(void) =
|
||||||
|
(void (*)(void)) CONFIG_PG_WCOM_UBOOT_UPDATE_TEXT_BASE;
|
||||||
|
char *isupdated = env_get("updateduboot");
|
||||||
|
ulong bootcount = bootcount_load();
|
||||||
|
ulong ebootcount = 0;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_PG_WCOM_UBOOT_BOOTPACKAGE)) {
|
||||||
|
/*
|
||||||
|
* When running in factory burned u-boot move to the updated
|
||||||
|
* u-boot version only if updateduboot envvar is set to 'yes'
|
||||||
|
* and bootcount limit is not exceeded.
|
||||||
|
* Board must be able to start in factory bootloader mode!
|
||||||
|
*/
|
||||||
|
if (isupdated && !strncmp(isupdated, "yes", 3) &&
|
||||||
|
bootcount <= CONFIG_BOOTCOUNT_BOOTLIMIT) {
|
||||||
|
printf("Check update: update detected, ");
|
||||||
|
printf("starting new image @%08x ...\n",
|
||||||
|
CONFIG_PG_WCOM_UBOOT_UPDATE_TEXT_BASE);
|
||||||
|
ebootcount = early_bootcount_load();
|
||||||
|
if (ebootcount <= CONFIG_BOOTCOUNT_BOOTLIMIT) {
|
||||||
|
early_bootcount_store(++ebootcount);
|
||||||
|
uboot_update_entry();
|
||||||
|
} else {
|
||||||
|
printf("Check update: warning: ");
|
||||||
|
printf("early bootcount exceeded (%lu)\n",
|
||||||
|
ebootcount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Check update: starting factory image @%08x ...\n",
|
||||||
|
CONFIG_SYS_TEXT_BASE);
|
||||||
|
} else if (IS_ENABLED(CONFIG_PG_WCOM_UBOOT_UPDATE)) {
|
||||||
|
/*
|
||||||
|
* When running in field updated u-boot, make sure that
|
||||||
|
* bootcount limit is never exceeded. Must never happen!
|
||||||
|
*/
|
||||||
|
WARN_ON(bootcount > CONFIG_BOOTCOUNT_BOOTLIMIT);
|
||||||
|
printf("Check update: updated u-boot starting @%08x ...\n",
|
||||||
|
CONFIG_SYS_TEXT_BASE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_SYS_I2C_INIT_BOARD)
|
#if defined(CONFIG_SYS_I2C_INIT_BOARD)
|
||||||
static void i2c_write_start_seq(void)
|
static void i2c_write_start_seq(void)
|
||||||
{
|
{
|
||||||
|
@ -135,6 +135,7 @@ int set_km_env(void);
|
|||||||
|
|
||||||
ulong early_bootcount_load(void);
|
ulong early_bootcount_load(void);
|
||||||
void early_bootcount_store(ulong ebootcount);
|
void early_bootcount_store(ulong ebootcount);
|
||||||
|
void check_for_uboot_update(void);
|
||||||
|
|
||||||
#define DELAY_ABORT_SEQ 62 /* @200kHz 9 clocks = 44us, 62us is ok */
|
#define DELAY_ABORT_SEQ 62 /* @200kHz 9 clocks = 44us, 62us is ok */
|
||||||
#define DELAY_HALF_PERIOD (500 / (CONFIG_SYS_I2C_SPEED / 1000))
|
#define DELAY_HALF_PERIOD (500 / (CONFIG_SYS_I2C_SPEED / 1000))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user