/* * 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 );