u-boot/common/cmd_recovery.c

140 lines
3.3 KiB
C

/*
* 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 <config.h>
#include <common.h>
#include <command.h>
#include <status_led.h>
#include <asm/gpio.h>
#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
);