Merge branch 'master' of git://git.denx.de/u-boot
[oweals/u-boot.git] / common / update.c
index 75284748734e11961cea3fb6258d4149e389112d..c8dd346a0956951a0683679bdd37d13c07383e60 100644 (file)
@@ -1,43 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2008 Semihalf
  *
  * Written by: Rafal Czubak <rcz@semihalf.com>
  *             Bartlomiej Sieka <tur@semihalf.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * 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., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
  */
 
 #include <common.h>
+#include <cpu_func.h>
+#include <image.h>
 
 #if !(defined(CONFIG_FIT) && defined(CONFIG_OF_LIBFDT))
 #error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature"
 #endif
 
-#if defined(CONFIG_SYS_NO_FLASH)
-#error "CONFIG_SYS_NO_FLASH defined, but FLASH is required for auto-update feature"
+#if defined(CONFIG_UPDATE_TFTP) && !defined(CONFIG_MTD_NOR_FLASH)
+#error "CONFIG_UPDATE_TFTP and !CONFIG_MTD_NOR_FLASH needed for legacy behaviour"
 #endif
 
 #include <command.h>
+#include <env.h>
 #include <flash.h>
 #include <net.h>
+#include <net/tftp.h>
 #include <malloc.h>
+#include <dfu.h>
+#include <errno.h>
+#include <mtd/cfi_flash.h>
 
 /* env variable holding the location of the update file */
 #define UPDATE_FILE_ENV                "updatefile"
 #define CONFIG_UPDATE_TFTP_CNT_MAX     0
 #endif
 
-extern ulong TftpRRQTimeoutMSecs;
-extern int TftpRRQTimeoutCountMax;
+extern ulong tftp_timeout_ms;
+extern int tftp_timeout_count_max;
+#ifdef CONFIG_MTD_NOR_FLASH
 extern flash_info_t flash_info[];
-extern ulong load_addr;
-
 static uchar *saved_prot_info;
-
+#endif
 static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
 {
        int size, rv;
@@ -71,22 +59,22 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
 
        rv = 0;
        /* save used globals and env variable */
-       saved_timeout_msecs = TftpRRQTimeoutMSecs;
-       saved_timeout_count = TftpRRQTimeoutCountMax;
-       saved_netretry = strdup(getenv("netretry"));
-       saved_bootfile = strdup(BootFile);
+       saved_timeout_msecs = tftp_timeout_ms;
+       saved_timeout_count = tftp_timeout_count_max;
+       saved_netretry = strdup(env_get("netretry"));
+       saved_bootfile = strdup(net_boot_file_name);
 
        /* set timeouts for auto-update */
-       TftpRRQTimeoutMSecs = msec_max;
-       TftpRRQTimeoutCountMax = cnt_max;
+       tftp_timeout_ms = msec_max;
+       tftp_timeout_count_max = cnt_max;
 
        /* we don't want to retry the connection if errors occur */
-       setenv("netretry", "no");
+       env_set("netretry", "no");
 
        /* download the update file */
-       load_addr = addr;
-       copy_filename(BootFile, filename, sizeof(BootFile));
-       size = NetLoop(TFTP);
+       image_load_addr = addr;
+       copy_filename(net_boot_file_name, filename, sizeof(net_boot_file_name));
+       size = net_loop(TFTPGET);
 
        if (size < 0)
                rv = 1;
@@ -94,21 +82,23 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
                flush_cache(addr, size);
 
        /* restore changed globals and env variable */
-       TftpRRQTimeoutMSecs = saved_timeout_msecs;
-       TftpRRQTimeoutCountMax = saved_timeout_count;
+       tftp_timeout_ms = saved_timeout_msecs;
+       tftp_timeout_count_max = saved_timeout_count;
 
-       setenv("netretry", saved_netretry);
+       env_set("netretry", saved_netretry);
        if (saved_netretry != NULL)
                free(saved_netretry);
 
        if (saved_bootfile != NULL) {
-               copy_filename(BootFile, saved_bootfile, sizeof(BootFile));
+               copy_filename(net_boot_file_name, saved_bootfile,
+                             sizeof(net_boot_file_name));
                free(saved_bootfile);
        }
 
        return rv;
 }
 
+#ifdef CONFIG_MTD_NOR_FLASH
 static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
 {
        uchar *sp_info_ptr;
@@ -180,9 +170,11 @@ static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
 
        return 0;
 }
+#endif
 
 static int update_flash(ulong addr_source, ulong addr_first, ulong size)
 {
+#ifdef CONFIG_MTD_NOR_FLASH
        ulong addr_last = addr_first + size - 1;
 
        /* round last address to the sector boundary */
@@ -218,7 +210,7 @@ static int update_flash(ulong addr_source, ulong addr_first, ulong size)
                printf("Error: could not protect flash sectors\n");
                return 1;
        }
-
+#endif
        return 0;
 }
 
@@ -238,28 +230,44 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
        return 0;
 }
 
-void update_tftp(void)
+int update_tftp(ulong addr, char *interface, char *devstring)
 {
-       char *filename, *env_addr;
-       int images_noffset, ndepth, noffset;
+       char *filename, *env_addr, *fit_image_name;
        ulong update_addr, update_fladdr, update_size;
-       ulong addr;
+       int images_noffset, ndepth, noffset;
+       bool update_tftp_dfu;
+       int ret = 0;
        void *fit;
 
+       if (interface == NULL && devstring == NULL) {
+               update_tftp_dfu = false;
+       } else if (interface && devstring) {
+               update_tftp_dfu = true;
+       } else {
+               pr_err("Interface: %s and devstring: %s not supported!\n",
+                     interface, devstring);
+               return -EINVAL;
+       }
+
+       /* use already present image */
+       if (addr)
+               goto got_update_file;
+
        printf("Auto-update from TFTP: ");
 
        /* get the file name of the update file */
-       filename = getenv(UPDATE_FILE_ENV);
+       filename = env_get(UPDATE_FILE_ENV);
        if (filename == NULL) {
                printf("failed, env. variable '%s' not found\n",
                                                        UPDATE_FILE_ENV);
-               return;
+               return 1;
        }
 
        printf("trying update file '%s'\n", filename);
 
        /* get load address of downloaded update file */
-       if ((env_addr = getenv("loadaddr")) != NULL)
+       env_addr = env_get("loadaddr");
+       if (env_addr)
                addr = simple_strtoul(env_addr, NULL, 16);
        else
                addr = CONFIG_UPDATE_LOAD_ADDR;
@@ -268,15 +276,16 @@ void update_tftp(void)
        if (update_load(filename, CONFIG_UPDATE_TFTP_MSEC_MAX,
                                        CONFIG_UPDATE_TFTP_CNT_MAX, addr)) {
                printf("Can't load update file, aborting auto-update\n");
-               return;
+               return 1;
        }
 
+got_update_file:
        fit = (void *)addr;
 
        if (!fit_check_format((void *)fit)) {
                printf("Bad FIT format of the update file, aborting "
                                                        "auto-update\n");
-               return;
+               return 1;
        }
 
        /* process updates */
@@ -288,11 +297,12 @@ void update_tftp(void)
                if (ndepth != 1)
                        goto next_node;
 
-               printf("Processing update '%s' :",
-                       fit_get_name(fit, noffset, NULL));
+               fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
+               printf("Processing update '%s' :", fit_image_name);
 
-               if (!fit_image_check_hashes(fit, noffset)) {
+               if (!fit_image_verify(fit, noffset)) {
                        printf("Error: invalid update hash, aborting\n");
+                       ret = 1;
                        goto next_node;
                }
 
@@ -301,15 +311,27 @@ void update_tftp(void)
                                        &update_fladdr, &update_size)) {
                        printf("Error: can't get update parameteres, "
                                                                "aborting\n");
+                       ret = 1;
                        goto next_node;
                }
-               if (update_flash(update_addr, update_fladdr, update_size)) {
-                       printf("Error: can't flash update, aborting\n");
-                       goto next_node;
+
+               if (!update_tftp_dfu) {
+                       if (update_flash(update_addr, update_fladdr,
+                                        update_size)) {
+                               printf("Error: can't flash update, aborting\n");
+                               ret = 1;
+                               goto next_node;
+                       }
+               } else if (fit_image_check_type(fit, noffset,
+                                               IH_TYPE_FIRMWARE)) {
+                       ret = dfu_tftp_write(fit_image_name, update_addr,
+                                            update_size, interface, devstring);
+                       if (ret)
+                               return ret;
                }
 next_node:
                noffset = fdt_next_node(fit, noffset, &ndepth);
        }
 
-       return;
+       return ret;
 }