From cfc204637d52d5f40fb2ec45c9108a1343b1984c 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. --- board/davinci/sysmobts_v2/sysmobts_v2.c | 19 +++- common/Makefile | 1 + common/cmd_recovery.c | 139 ++++++++++++++++++++++++ include/configs/davinci_sysmobts_v2.h | 10 +- 4 files changed, 165 insertions(+), 4 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 cc48d21aac..645f86d0db 100644 --- a/board/davinci/sysmobts_v2/sysmobts_v2.c +++ b/board/davinci/sysmobts_v2/sysmobts_v2.c @@ -1,5 +1,7 @@ /* * Copyright (C) 2012 sysmocom s.f.m.c. GmbH + * Author: Holger Hans Peter Freyther + * * Copyright (C) 2009 Lyrtech RD Inc. * * Based on dvevm/dvevm.c, original copyright follows: @@ -150,12 +152,23 @@ int board_init(void) lpsc_on(DAVINCI_LPSC_TIMER1); timer_init(); - /* configure LEDs */ - status_led_set(0, STATUS_LED_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, STATUS_LED_ON); + } else { + /* configure LEDs */ + status_led_set(0, STATUS_LED_OFF); + } +#endif +} + int misc_init_r(void) { uint8_t eeprom_enetaddr[6]; diff --git a/common/Makefile b/common/Makefile index 54fcc81588..ef60347bf6 100644 --- a/common/Makefile +++ b/common/Makefile @@ -179,6 +179,7 @@ COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o COBJS-$(CONFIG_CMD_SPL) += cmd_spl.o COBJS-$(CONFIG_CMD_ZIP) += cmd_zip.o COBJS-$(CONFIG_CMD_ZFS) += cmd_zfs.o +COBJS-$(CONFIG_CMD_RECOVERY) += cmd_recovery.o # others ifdef CONFIG_DDR_SPD diff --git a/common/cmd_recovery.c b/common/cmd_recovery.c new file mode 100644 index 0000000000..108a86b4f3 --- /dev/null +++ b/common/cmd_recovery.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2012 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, STATUS_LED_OFF); \ + udelay(900); \ + status_led_set(0, STATUS_LED_ON); \ + } \ + status_led_set(0, STATUS_LED_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, const char *argv[]) +{ + int rc; + + status_led_set(0, STATUS_LED_ON); + printf("Starting the recovery process.\n"); + + /* Wait a bit and check if the reset button is still pressed */ + 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, STATUS_LED_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; set 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; " + "set 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", NULL +); diff --git a/include/configs/davinci_sysmobts_v2.h b/include/configs/davinci_sysmobts_v2.h index 6355fc24a9..f715034e9a 100644 --- a/include/configs/davinci_sysmobts_v2.h +++ b/include/configs/davinci_sysmobts_v2.h @@ -99,7 +99,7 @@ "nand0=davinci_nand.0" #define MTDPARTS_DEFAULT \ "mtdparts=davinci_nand.0:" \ - "128k(U-Boot Params)ro," \ + "128k(U-Boot-Environment)ro," \ "384k(UBL)ro," \ "512k(U-Boot)ro," \ "-(RootFs)" @@ -204,6 +204,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