From ef64beafdc6e58a16ce5fb5939a06c77e04c7421 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 14 Jul 2012 13:16:49 +0200 Subject: [PATCH] sysmobts-v2: Introduce a recovery command to reflash the system image When pressing the reset button on boot the system will enter the recovery mode, this is done by setting a preboot command. Inside the preboot command we will sleep and then check if the button is still pressed, then tftp will be used to download the image and flash it. If something fails after the DHCP state the network console will be enabled. recovery: Make it possible to force the recovery For factory flashing it is the easiest if we can force the recovery process. Parse the "force" from a potential second argument and then skip the timeout. --- board/davinci/sysmobts_v2/sysmobts_v2.c | 19 +++- common/Makefile | 1 + common/cmd_recovery.c | 144 ++++++++++++++++++++++++ include/configs/davinci_sysmobts_v2.h | 8 ++ scripts/config_whitelist.txt | 1 + 5 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 common/cmd_recovery.c diff --git a/board/davinci/sysmobts_v2/sysmobts_v2.c b/board/davinci/sysmobts_v2/sysmobts_v2.c index dbea937fa7..c40358a9b0 100644 --- a/board/davinci/sysmobts_v2/sysmobts_v2.c +++ b/board/davinci/sysmobts_v2/sysmobts_v2.c @@ -32,6 +32,7 @@ #include #include #include +#include #define DAVINCI_PLLM (0x01C40910) /* PLL 1 Multiplier */ #define DAVINCI_AWCCR (0x01E00004) /* EMIF-A async wait cycle config register. */ @@ -139,12 +140,24 @@ int board_init(void) lpsc_on(DAVINCI_LPSC_TIMER1); timer_init(); - /* configure LEDs */ - status_led_set(0, CONFIG_LED_STATUS_OFF); - return(0); } +int board_late_init(void) +{ +#ifdef CONFIG_PREBOOT + /* remember if we are in reset */ + if (gpio_get_value(38) == 0) { + setenv("preboot", "run_recovery"); + status_led_set(0, CONFIG_LED_STATUS_ON); + } else { + /* configure LEDs */ + status_led_set(0, CONFIG_LED_STATUS_OFF); + } +#endif + return 0; +} + int misc_init_r(void) { uint8_t eeprom_enetaddr[6]; diff --git a/common/Makefile b/common/Makefile index 86225f1564..43549a7d55 100644 --- a/common/Makefile +++ b/common/Makefile @@ -63,6 +63,7 @@ ifdef CONFIG_CMD_USB obj-y += usb.o usb_hub.o obj-$(CONFIG_USB_STORAGE) += usb_storage.o endif +obj-$(CONFIG_CMD_RECOVERY) += cmd_recovery.o # others obj-$(CONFIG_BOOTSTAGE) += bootstage.o diff --git a/common/cmd_recovery.c b/common/cmd_recovery.c new file mode 100644 index 0000000000..5ba5b9e576 --- /dev/null +++ b/common/cmd_recovery.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2012, 2013, 2015, 2017 sysmocom s.f.m.c. GmbH + * Author: Holger Hans Peter Freyther + + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include + +#define BLINK_LED(LEN) \ + do { \ + int i; \ + for (i = 0; i < LEN; ++i) { \ + status_led_set(0, CONFIG_LED_STATUS_OFF); \ + udelay(900); \ + status_led_set(0, CONFIG_LED_STATUS_ON); \ + } \ + status_led_set(0, CONFIG_LED_STATUS_OFF); \ + } while(0); + +static int enable_netconsole(void) +{ + printf("Enabling the network console.\n"); + + /* reset in 60s if it is not interrupted */ + return run_command("setenv stdout nc; setenv stdin nc", 0); +} + +static int env_failed(void) +{ + printf("Environment clearing failed.\n"); + + BLINK_LED(7); + return -1; +} + +static int dhcp_failed(void) +{ + printf("DHCP failed. Giving up on recovery.\n"); + + BLINK_LED(10); + return -1; +} + +static int tftp_failed(void) +{ + printf("TFTP failed.\n"); + BLINK_LED(13); + enable_netconsole(); + return -1; +} + +static int flash_failed(void) +{ + printf("Flash failed.\n"); + BLINK_LED(15); + enable_netconsole(); + return -1; +} + +/** + * This will run the recovery process. + * 1.) Enable the LED to give instant feedback. + * 2.) Clear the environment in case of bad configuration. + * 3.) Get a DHCP lease. + * 4.) Try to tftpboot + * 5.) Try to tftpboot with a different server + * 6.) Flash + * 7.) Reset or enter netconsole + */ +static int do_run_recovery(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int rc; + + status_led_set(0, CONFIG_LED_STATUS_ON); + printf("Starting the recovery process.\n"); + + /* Wait a bit and check if the reset button is still pressed */ + if (argc == 2 && strcmp(argv[1], "force") == 0) { + printf("Forcing the recovery process.\n"); + } else { + run_command("sleep 5", 0); + if (gpio_get_value(38) != 0) { + printf("Recovery process aborted.\n"); + run_command("dhcp", 0); + enable_netconsole(); + BLINK_LED(4); + return 0; + } + } + + BLINK_LED(5); + status_led_set(0, CONFIG_LED_STATUS_ON); + + rc = run_command("mtdpart default; " + "nand erase.part U-Boot-Environment", 0); + if (rc != 0) + return env_failed(); + + rc = run_command("setenv autoload no; setenv netretry no; dhcp", 0); + if (rc != 0) + return dhcp_failed(); + + rc = run_command("setenv filesize 0; " + "tftp 85000000 sysmocom-recovery.ubi", 0); + if (rc != 0) { + rc = run_command("setenv filesize 0; " + "setenv serverip 255.255.255.255; " + "tftp 85000000 sysmocom-recovery.ubi", 0); + } + + if (rc != 0) + return tftp_failed(); + + rc = run_command("nand erase.part RootFs; " + "nand write 85000000 RootFs ${filesize} ", 0); + if (rc != 0) + return flash_failed(); + + return run_command("reset", 0); +} + +U_BOOT_CMD( + run_recovery, CONFIG_SYS_MAXARGS, 1, do_run_recovery, + "Run the sysmocom sysmoBTS recovery process", + "[force]" +); diff --git a/include/configs/davinci_sysmobts_v2.h b/include/configs/davinci_sysmobts_v2.h index e9826f4785..21517a1901 100644 --- a/include/configs/davinci_sysmobts_v2.h +++ b/include/configs/davinci_sysmobts_v2.h @@ -189,6 +189,14 @@ #define CONFIG_DM644X_GPIO #define CONFIG_CMD_GPIO +/*=======================*/ +/* Recovery handling */ +/*=======================*/ +#define CONFIG_PREBOOT +#define CONFIG_CMD_RECOVERY +#define CONFIG_NETCONSOLE +#define CONFIG_BOARD_LATE_INIT + /* bdinfo should show the clocks */ #ifdef CONFIG_CMD_BDI diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 98d135283f..0ec067b00b 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -526,6 +526,7 @@ CONFIG_CMD_PCI_ENUM CONFIG_CMD_PCMCIA CONFIG_CMD_PORTIO CONFIG_CMD_READ +CONFIG_CMD_RECOVERY CONFIG_CMD_REGINFO CONFIG_CMD_REISER CONFIG_CMD_SANDBOX