diff --git a/u-boot/common/cmd_recovery.c b/u-boot/common/cmd_recovery.c new file mode 100644 index 0000000000..108a86b4f3 --- /dev/null +++ b/u-boot/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 +);