mvsource: add new command to burn and run scripts
- add 'mvsource' command to burn U-Boot scripts to flash
and run burned scripts (using 'source' command).
- add 'run_script' environment variable, when set to 'yes'
run burned script from flash on late boot stage (in 'misc_init_r')
** scripts' image is compiled using the mkimage tool
** scripts can be fetched from TFTP or USB.
Change-Id: Icca6a396fc78a9080d78717ac89cd273544e7b7f
Signed-off-by: Bassel Saba <basselsa@marvell.com>
Reviewed-on: http://vgitil04.il.marvell.com:8080/19022
Reviewed-by: Omri Itach <omrii@marvell.com>
Tested-by: Star_Automation <star@marvell.com>
diff --git a/board/mv_ebu/a375/mv_main_a375.c b/board/mv_ebu/a375/mv_main_a375.c
index e128db8..3840113 100755
--- a/board/mv_ebu/a375/mv_main_a375.c
+++ b/board/mv_ebu/a375/mv_main_a375.c
@@ -491,6 +491,12 @@
if (!env)
setenv("initrd_name", "uInitrd");
+#ifdef CONFIG_CMD_SOURCE
+ env = getenv("run_script");
+ if (!env)
+ setenv("run_script", "no");
+#endif
+
/* netbsd boot arguments */
env = getenv("netbsd_en");
if ( !env || ( ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0) )))
@@ -1044,7 +1050,12 @@
#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH)
mvBoardEgigaPhyInit();
#endif
-
+#ifdef CONFIG_CMD_SOURCE
+ /* run saved script */
+ env = getenv("run_script");
+ if (env && strcmp(env, "yes") == 0)
+ run_command("mvsource run", 0);
+#endif
return 0;
}
diff --git a/board/mv_ebu/a38x/mv_main_a38x.c b/board/mv_ebu/a38x/mv_main_a38x.c
index 4b43a9c..e9e687e 100755
--- a/board/mv_ebu/a38x/mv_main_a38x.c
+++ b/board/mv_ebu/a38x/mv_main_a38x.c
@@ -531,6 +531,12 @@
if (!env)
setenv("initrd_name", "uInitrd");
+#ifdef CONFIG_CMD_SOURCE
+ env = getenv("run_script");
+ if (!env)
+ setenv("run_script", "no");
+#endif
+
/* netbsd boot arguments */
env = getenv("netbsd_en");
if ( !env || ( ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0) )))
@@ -1088,13 +1094,20 @@
setenv("pcieTune", "no");
+
+
#if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH)
mvBoardEgigaPhyInit();
#endif
#if defined(CONFIG_CMD_DATE)
rtc_init(); /* Ensure the bus bridge parameters are ready for RTC access */
#endif
-
+#ifdef CONFIG_CMD_SOURCE
+ /* run saved script */
+ env = getenv("run_script");
+ if (env && strcmp(env, "yes") == 0)
+ run_command("mvsource run", 0);
+#endif
return 0;
}
diff --git a/board/mv_ebu/alp/mv_main_alp.c b/board/mv_ebu/alp/mv_main_alp.c
index 99ae9b5..320969a 100644
--- a/board/mv_ebu/alp/mv_main_alp.c
+++ b/board/mv_ebu/alp/mv_main_alp.c
@@ -494,6 +494,12 @@
if (!env)
setenv("initrd_name", "uInitrd");
+#ifdef CONFIG_CMD_SOURCE
+ env = getenv("run_script");
+ if (!env)
+ setenv("run_script", "no");
+#endif
+
/* netbsd boot arguments */
env = getenv("netbsd_en");
if ( !env || ( ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0) )))
@@ -1069,7 +1075,12 @@
mvBoardEgigaPhyInit();
#endif
#endif
-
+#ifdef CONFIG_CMD_SOURCE
+ /* run saved script */
+ env = getenv("run_script");
+ if (env && strcmp(env, "yes") == 0)
+ run_command("mvsource run", 0);
+#endif
return 0;
}
diff --git a/board/mv_ebu/common/Makefile b/board/mv_ebu/common/Makefile
index 801ffa9..4f68969 100644
--- a/board/mv_ebu/common/Makefile
+++ b/board/mv_ebu/common/Makefile
@@ -104,6 +104,7 @@
$(USP_DIR)/mv_cmd.o \
$(USP_DIR)/mv_dram.o \
$(USP_DIR)/cmd_bubt.o \
+ $(USP_DIR)/cmd_mvsource.o \
$(USP_DIR)/cmd_resetenv.o \
$(USP_DIR)/mvDramScrubbing.o \
$(USP_DIR)/cmd_ddr.o \
diff --git a/board/mv_ebu/common/USP/cmd_mvsource.c b/board/mv_ebu/common/USP/cmd_mvsource.c
new file mode 100644
index 0000000..70502b0
--- /dev/null
+++ b/board/mv_ebu/common/USP/cmd_mvsource.c
@@ -0,0 +1,538 @@
+#include <config.h>
+#include <common.h>
+#include "mvCommon.h"
+#include <command.h>
+#include <net.h>
+#include <environment.h>
+
+#ifdef CONFIG_CMD_SOURCE
+#if defined(MV_INCLUDE_USB)
+#include <usb.h>
+#endif
+
+#include <fs.h>
+
+#define DESTINATION_STRING 10
+
+#if defined(CONFIG_CMD_NAND)
+#include <nand.h>
+extern nand_info_t nand_info[]; /* info for NAND chips */
+#endif
+
+#ifdef CONFIG_CMD_SF
+#include <spi_flash.h>
+extern struct spi_flash *flash;
+#endif
+
+#ifdef CONFIG_CMD_FLASH
+#include <flash.h>
+extern flash_info_t flash_info[]; /* info for FLASH chips */
+#endif
+
+#include <image.h>
+#include <malloc.h>
+
+int dest_flash; /* destination flash to burn the script (0 = SPI, 1 = NAND) */
+
+#ifdef MV_INCLUDE_USB
+/*******************************************************************************
+* load_from_usb
+*
+* DESCRIPTION:
+* Load script file from usb device
+*
+* INPUT:
+* file_name - img file name.
+*
+* OUTPUT:
+* None.
+*
+* RETURN:
+* - file size on success
+* - 0, otherwise
+*
+*******************************************************************************/
+static int load_from_usb(const char *file_name)
+{
+ const char *addr_str;
+ unsigned long addr;
+ int filesize = 0;
+
+ usb_stop();
+ printf("(Re)start USB...\n");
+
+ if (usb_init() < 0) {
+ printf("usb_init failed\n");
+ return 0;
+ }
+
+ /* try to recognize storage devices immediately */
+ /* the parameter '1', tells the function to reports to the
+ * user while scanning for device */
+ if (-1 == usb_stor_scan(1)) {
+ printf("USB storage device not found\n");
+ return 0;
+ }
+
+ /* always load from usb 0 */
+ if (fs_set_blk_dev("usb", "0", FS_TYPE_ANY)) {
+ printf("USB 0 not found\n");
+ return 0;
+ }
+
+ addr_str = getenv("loadaddr");
+ if (addr_str != NULL)
+ addr = simple_strtoul(addr_str, NULL, 16);
+ else
+ addr = CONFIG_SYS_LOAD_ADDR;
+
+ filesize = fs_read(file_name, addr, 0, 0);
+ return filesize;
+}
+#endif
+
+/*******************************************************************************
+* fetch_script_file
+*
+* DESCRIPTION:
+* Load script file into ram from external device: tftp, usb
+*
+* INPUT:
+* loadfrom - specifies the source device:
+* 0 - TFTP, 1 - USB
+*
+* OUTPUT:
+* None.
+*
+* RETURN:
+* - file size on success
+* - 0, otherwise
+*
+*******************************************************************************/
+static int fetch_script_file(int loadfrom)
+{
+ int filesize = 0;
+ switch (loadfrom) {
+#ifdef MV_INCLUDE_USB
+ case 1:
+ filesize = load_from_usb(BootFile);
+ if (filesize <= 0) {
+ printf("Failed to read file %s\n", BootFile);
+ return 0;
+ }
+ break;
+#endif
+ case 0:
+ filesize = NetLoop(TFTPGET);
+ printf("Checking file size:");
+ if (filesize == -1) {
+ printf("\t[Fail]\n");
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return filesize;
+}
+
+/*******************************************************************************
+* fetch_mvsource_cmd_args
+*
+* DESCRIPTION:
+* fetch command arguments from argv and return them in variables
+*
+* INPUT:
+* argc - command arguments' number
+* argv - command arguments' values
+*
+* OUTPUT:
+* command - command to run (0 = burn, 1 = run)
+* offset - offset in flash to burn the script
+* loadfrom - source interface (0 = TFTP, 1 = USB)
+* dest - destination flash if multiple flashes supported
+* (0 = SPI, 1 = NAND)
+*
+* RETURN:
+* - MV_OK on success
+* - MV_FAIL, otherwise
+*
+*******************************************************************************/
+static MV_STATUS fetch_mvsource_cmd_args(int argc, char * const argv[],
+ int *command, MV_U32 *offset, int *loadfrom, int *dest) {
+ int i;
+ const char *default_name = "script.img";
+
+ *command = -1; /* 0 = burn; 1 = run; -1 = invalid command */
+ *offset = 0x300000;
+ *loadfrom = 0; /* 0 = TFTP; 1 = USB */
+ *dest = 0; /* 0 = SPI; 1 = NAND */
+
+ /* fetch destination interface (if exists), else use SPI as default */
+ for (i = 0; i < argc; ++i) {
+ if (strcmp(argv[i], "spi") == 0) {
+ *dest = 0;
+ argc--;
+ break;
+ } else if (strcmp(argv[i], "nand") == 0) {
+ *dest = 1;
+ argc--;
+ break;
+ }
+ }
+
+ if (argc < 2) { /* empty command is unacceptable */
+ printf("Error: too few arguments\n");
+ return MV_FAIL;
+ }
+
+ /* skip main command name */
+ argc--;
+ argv++;
+ if (strcmp(argv[0], "burn") == 0) {
+ *command = 0;
+ /* only burn command have filename as 1st parameter */
+ if (argc > 1) {
+ strncpy(BootFile, argv[1], strlen(argv[1]));
+ argc--;
+ argv++;
+ } else {
+ strncpy(BootFile, default_name, strlen(default_name));
+ printf("using default filename \"%s\"\n", default_name);
+ }
+ } else if (strcmp(argv[0], "run") == 0)
+ *command = 1;
+ else {
+ printf("Error: unknown command\n");
+ return MV_FAIL;
+ }
+
+ /* skip internal command name ('burn' or 'run') */
+ argc--;
+ argv++;
+ switch (argc) {
+ case 2:
+ if (strcmp(argv[1], "tftp") == 0)
+ *loadfrom = 0;
+ else if (strcmp(argv[1], "usb") == 0)
+ *loadfrom = 1;
+ else
+ return MV_FAIL;
+ case 1:
+ *offset = simple_strtoul(argv[0], NULL, 16);
+ default:
+ break;
+ }
+ return MV_OK;
+}
+
+#if defined(MV_INCLUDE_SPI)
+/*******************************************************************************
+* init_spi
+*
+* DESCRIPTION:
+* init spi flash if not initiated
+*
+* INPUT:
+* None.
+*
+* OUTPUT:
+* None.
+*
+* RETURN:
+* 0 on success
+* -1 otherwise
+*
+*******************************************************************************/
+static int init_spi(void){
+ if (!flash) {
+ flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
+ CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
+ if (!flash) {
+ printf("Failed to probe SPI Flash\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*******************************************************************************
+* spi_burn_script
+*
+* DESCRIPTION:
+* burn script image to the SPI flash
+*
+* INPUT:
+* offset - offset in flash to burn the script
+* loadfrom - source interface to fetch the file (0 = TFTP, 1 = USB)
+*
+* OUTPUT:
+* None.
+*
+* RETURN:
+* None.
+*
+*******************************************************************************/
+static void spi_burn_script(MV_U32 offset, int loadfrom)
+{
+ int filesize = 0;
+ MV_U32 ret = 0;
+ load_addr = CONFIG_SYS_LOAD_ADDR;
+ u32 sector_size, aligned_size;
+
+ if (init_spi())
+ return;
+
+ sector_size = flash->sector_size;
+
+ /* verify requested source is valid */
+ filesize = fetch_script_file(loadfrom);
+ if (filesize <= 0)
+ return;
+
+ aligned_size = ((filesize + (sector_size - 1)) & (~(sector_size - 1)));
+ printf("Erasing 0x%x - 0x%x: ", offset, offset + aligned_size);
+ spi_flash_erase(flash, offset, aligned_size);
+ printf("\t\t[Done]\n");
+
+ printf("Writing image to flash:");
+ ret = spi_flash_write(flash, offset, filesize, (const void *)load_addr);
+
+ if (ret)
+ printf("\t\t[Err!]\n");
+ else
+ printf("\t\t[Done]\n");
+}
+#endif /* MV_INCLUDE_SPI */
+
+#if defined(MV_NAND)
+/*******************************************************************************
+* spi_burn_script
+*
+* DESCRIPTION:
+* burn script image to the NAND flash
+*
+* INPUT:
+* offset - offset in flash to burn the script
+* loadfrom - source interface to fetch the file (0 = TFTP, 1 = USB)
+*
+* OUTPUT:
+* None.
+*
+* RETURN:
+* None.
+*
+*******************************************************************************/
+static void nand_burn_script(MV_U32 offset, int loadfrom)
+{
+ int filesize = 0;
+ MV_U32 ret = 0, aligned_size;
+ nand_info_t *nand = &nand_info[0];
+ size_t erasesize = nand_info[0].erasesize;
+
+ if (nand_block_isbad(&nand_info[0], offset)) {
+ printf("Failed to burn: Bad block at offset %X\n", offset);
+ return;
+ }
+
+ /* verify requested source is valid */
+ filesize = fetch_script_file(loadfrom);
+ if (filesize <= 0)
+ return;
+
+ aligned_size = ((filesize + (erasesize - 1)) & (~(erasesize - 1)));
+ printf("\t[Done]\n");
+ printf("Erasing 0x%x - 0x%x: ", offset, offset + aligned_size);
+ nand_erase(nand, offset, aligned_size);
+ printf("\t[Done]\n");
+
+ printf("Writing image to NAND:");
+ ret = nand_write(nand, offset, (size_t *)&filesize, (u_char *)load_addr);
+ if (ret)
+ printf("\t[Fail]\n");
+ else
+ printf("\t[Done]\n");
+}
+#endif /* defined(MV_NAND) */
+
+/*******************************************************************************
+* is_magic_valid
+*
+* DESCRIPTION:
+* checks if the magic value in script header is valid
+*
+* INPUT:
+* header - script header
+*
+* RETURN:
+* MV_TRUE if magic value in header is valid
+* MV_FALSE otherwise
+*
+*******************************************************************************/
+MV_BOOL is_magic_valid(image_header_t *header)
+{
+ /* check if image type is IMAGE_FORMAT_LEGACY */
+ if (be32_to_cpu(header->ih_magic) != IH_MAGIC)
+ return MV_FALSE;
+
+ return MV_TRUE;
+}
+
+/*******************************************************************************
+* get_image_size
+*
+* DESCRIPTION:
+* fetch script size (in bytes) from script header
+*
+* INPUT:
+* offset - script offset in flash
+*
+* OUTPUT:
+* size - script size (in bytes)
+*
+* RETURN:
+* MV_OK on success fetching the size
+* MV_FAIL otherwise
+*
+*******************************************************************************/
+MV_STATUS get_image_size(MV_U32 offset, MV_U32 *size)
+{
+ size_t buff_size = sizeof(image_header_t);
+ image_header_t header;
+#if defined(MV_INCLUDE_SPI)
+ if (init_spi())
+ return MV_FAIL;
+#endif
+#if defined(MV_INCLUDE_SPI) && defined(MV_NAND)
+ if (dest_flash == 0)
+ spi_flash_read(flash, offset, buff_size , &header);
+ else if (dest_flash == 1)
+ nand_read(&nand_info[0], offset, &buff_size, (u_char *)&header);
+#elif defined(MV_INCLUDE_SPI)
+ spi_flash_read(flash, offset, buff_size , &header);
+#elif defined(MV_NAND)
+ nand_read(&nand_info[0], offset, &buff_size, (u_char *)&header);
+#else
+ return MV_FAIL;
+#endif
+ if (is_magic_valid(&header) == MV_FALSE)
+ return MV_FAIL;
+
+ *size = be32_to_cpu(header.ih_size) + sizeof(image_header_t);
+ return MV_OK;
+}
+
+/*******************************************************************************
+* get_block_size
+*
+* DESCRIPTION:
+* get block size of flash
+*
+* INPUT:
+* None.
+*
+* OUTPUT:
+* None.
+*
+* RETURN:
+* block size, on success
+* 0, otherwise
+*
+*******************************************************************************/
+MV_U32 get_block_size(void)
+{
+#if defined(MV_INCLUDE_SPI) && defined(MV_NAND)
+ if (dest_flash == 0)
+ return flash->sector_size;
+ else if (dest_flash == 1)
+ return nand_info[0].erasesize;
+ else
+ return 0;
+#elif defined(MV_INCLUDE_SPI)
+ return flash->sector_size;
+
+#elif defined(MV_NAND)
+ return nand_info[0].erasesize;
+#else
+ return 0;
+#endif
+}
+
+int mvsource_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int command, loadfrom;
+ MV_U32 offset;
+ char *buffer;
+ char buffer_address_str[30]; /* to pass to 'source' argument */
+ MV_U32 size;
+ char *source_argv[2];
+
+ if (fetch_mvsource_cmd_args(argc, argv, &command,
+ &offset, &loadfrom, &dest_flash) != MV_OK)
+ return 1;
+
+
+ if (command == 0) { /* 0 = burn */
+#if defined(MV_INCLUDE_SPI) && defined(MV_NAND)
+ if (dest_flash == 0)
+ spi_burn_script(offset, loadfrom);
+ else if (dest_flash == 1)
+ nand_burn_script(offset, loadfrom);
+#elif defined(MV_INCLUDE_SPI)
+ spi_burn_script(offset, loadfrom);
+#elif defined(MV_NAND)
+ nand_burn_script(offset, loadfrom);
+#endif
+ } else if (command == 1) { /* 1 = run */
+ if (get_image_size(offset, &size) != MV_OK) {
+ printf("Error: Failed to fetch script size\n");
+ return 1;
+ } else {
+ buffer = (char *)malloc(size);
+ if (!buffer) {
+ printf("Error: Failed to allocate memory\n");
+ return 1;
+ }
+ }
+#if defined(MV_INCLUDE_SPI) && defined(MV_NAND)
+ if (dest_flash == 0)
+ spi_flash_read(flash, offset, size , buffer);
+ else if (dest_flash == 1)
+ nand_read(&nand_info[0], offset, &size, (u_char *)buffer);
+#elif defined(MV_INCLUDE_SPI)
+ spi_flash_read(flash, offset, size , buffer);
+#elif defined(MV_NAND)
+ nand_read(&nand_info[0], offset, &size, (u_char *)buffer);
+#else
+ return 1;
+#endif
+ sprintf(buffer_address_str, "%lx", (unsigned long)buffer);
+ source_argv[0] = "source";
+ source_argv[1] = buffer_address_str;
+ do_source(cmdtp, 0, 2, source_argv);
+ free(buffer);
+ }
+ return 0;
+}
+
+U_BOOT_CMD(
+ mvsource, 5, 1, mvsource_cmd,
+ "mvsource - Burn a script image on flash device.\n",
+ "burn [file-name [offset [src_interface]]] [dst_flash]"
+ "\n\tBurn script <file-name> to flash at <offset> from <src_interface> \n"
+ "mvsource run [offset]"
+ "\n\tRun script from flash at <offset>\n"
+ "\nArguments (optional):\n"
+ "\t- file-name: script file name\t\t\t(default = script.bin)\n"
+ "\t- offset: script address in flash\t\t(default = 300000)\n"
+ "\t- src_interface: script source: tftp/usb\t(default = tftp)\n"
+ "\t- dst_flash: flash destination: spi/nand\t(default = spi)\n"
+ "Examples:\n"
+ "\tmvsource burn script.img 300000 tftp spi\n"
+ "\tmvsource burn\n"
+ "\tmvsource run 300000\n"
+ "\tmvsource run\n"
+ );
+
+#endif /* CONFIG_CMD_SOURCE */
diff --git a/board/mv_ebu/common/USP/mv_main.c b/board/mv_ebu/common/USP/mv_main.c
index 3165404..2bc8aa4 100755
--- a/board/mv_ebu/common/USP/mv_main.c
+++ b/board/mv_ebu/common/USP/mv_main.c
@@ -392,6 +392,9 @@
envSetDefault("bootcmd_lgcy", "tftpboot 0x2000000 $image_name; setenv bootargs $bootargs_dflt; bootm 0x2000000; ");
#endif /* #if defined (CONFIG_CMD_STAGE_BOOT) */
+#ifdef CONFIG_CMD_SOURCE
+ envSetDefault("run_script", "no");
+#endif
/* netbsd boot arguments */
env = getenv("netbsd_en");
if( !env || ( ((strcmp(env,"no") == 0) || (strcmp(env,"No") == 0) ))) {
@@ -697,7 +700,12 @@
/* Init the PHY or Switch of the board */
mvBoardEgigaPhyInit();
#endif /* #if defined(MV_INCLUDE_UNM_ETH) || defined(MV_INCLUDE_GIG_ETH) */
-
+#ifdef CONFIG_CMD_SOURCE
+ /* run saved script */
+ env = getenv("run_script");
+ if (env && strcmp(env, "yes") == 0)
+ run_command("mvsource run", 0);
+#endif
return 0;
}