]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/cmd_fdt.c
include/bitfield.h: Assure new bitfield value doesn't touch unwanted bits
[karo-tx-uboot.git] / common / cmd_fdt.c
index 6eec947fcb3ecbf572120b0b9fce7c0de2d94587..4c18962d853283b501729d0b36c6326548c00a1c 100644 (file)
@@ -5,23 +5,7 @@
  *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
  *   Matthew McClintock <msm@freescale.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
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
@@ -31,6 +15,8 @@
 #include <asm/global_data.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <mapmem.h>
+#include <asm/io.h>
 
 #define MAX_LEVEL      32              /* how deeply nested we will go */
 #define SCRATCHPAD     1024            /* bytes of scratchpad memory */
@@ -43,7 +29,7 @@
  */
 DECLARE_GLOBAL_DATA_PTR;
 
-static int fdt_valid(void);
+static int fdt_valid(struct fdt_header **blobp);
 static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
 static int fdt_print(const char *pathp, char *prop, int depth);
 static int is_printable_string(const void *data, int len);
@@ -53,14 +39,13 @@ static int is_printable_string(const void *data, int len);
  */
 struct fdt_header *working_fdt;
 
-void set_working_fdt_addr(void *addr)
+void set_working_fdt_addr(ulong addr)
 {
-       char buf[17];
+       void *buf;
 
-       working_fdt = addr;
-
-       sprintf(buf, "%lx", (unsigned long)addr);
-       setenv("fdtaddr", buf);
+       buf = map_sysmem(addr, 0);
+       working_fdt = buf;
+       setenv_hex("fdtaddr", addr);
 }
 
 /*
@@ -104,40 +89,59 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
         */
        if (argv[1][0] == 'a') {
                unsigned long addr;
+               int control = 0;
+               struct fdt_header *blob;
                /*
                 * Set the address [and length] of the fdt.
                 */
-               if (argc == 2) {
-                       if (!fdt_valid()) {
+               argc -= 2;
+               argv += 2;
+/* Temporary #ifdef - some archs don't have fdt_blob yet */
+#ifdef CONFIG_OF_CONTROL
+               if (argc && !strcmp(*argv, "-c")) {
+                       control = 1;
+                       argc--;
+                       argv++;
+               }
+#endif
+               if (argc == 0) {
+                       if (control)
+                               blob = (struct fdt_header *)gd->fdt_blob;
+                       else
+                               blob = working_fdt;
+                       if (!blob || !fdt_valid(&blob))
                                return 1;
-                       }
-                       printf("The address of the fdt is %p\n", working_fdt);
+                       printf("The address of the fdt is %#08lx\n",
+                              control ? (ulong)map_to_sysmem(blob) :
+                                       getenv_hex("fdtaddr", 0));
                        return 0;
                }
 
-               addr = simple_strtoul(argv[2], NULL, 16);
-               set_working_fdt_addr((void *)addr);
-
-               if (!fdt_valid()) {
+               addr = simple_strtoul(argv[0], NULL, 16);
+               blob = map_sysmem(addr, 0);
+               if (!fdt_valid(&blob))
                        return 1;
-               }
+               if (control)
+                       gd->fdt_blob = blob;
+               else
+                       set_working_fdt_addr(addr);
 
-               if (argc >= 4) {
+               if (argc >= 2) {
                        int  len;
                        int  err;
                        /*
                         * Optional new length
                         */
-                       len = simple_strtoul(argv[3], NULL, 16);
-                       if (len < fdt_totalsize(working_fdt)) {
+                       len = simple_strtoul(argv[1], NULL, 16);
+                       if (len < fdt_totalsize(blob)) {
                                printf ("New length %d < existing length %d, "
                                        "ignoring.\n",
-                                       len, fdt_totalsize(working_fdt));
+                                       len, fdt_totalsize(blob));
                        } else {
                                /*
                                 * Open in place with a new length.
                                 */
-                               err = fdt_open_into(working_fdt, working_fdt, len);
+                               err = fdt_open_into(blob, blob, len);
                                if (err != 0) {
                                        printf ("libfdt fdt_open_into(): %s\n",
                                                fdt_strerror(err));
@@ -171,9 +175,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                 * Set the address and length of the fdt.
                 */
                working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
-               if (!fdt_valid()) {
+               if (!fdt_valid(&working_fdt))
                        return 1;
-               }
 
                newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
 
@@ -347,10 +350,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        }
                        if (subcmd[0] == 's') {
                                /* get the num nodes at this level */
-                               char buf[11];
-
-                               sprintf(buf, "%d", curIndex + 1);
-                               setenv(var, buf);
+                               setenv_ulong(var, curIndex + 1);
                        } else {
                                /* node index not found */
                                printf("libfdt node not found\n");
@@ -567,11 +567,30 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        }
 #ifdef CONFIG_OF_BOARD_SETUP
        /* Call the board-specific fixup routine */
-       else if (strncmp(argv[1], "boa", 3) == 0)
-               ft_board_setup(working_fdt, gd->bd);
+       else if (strncmp(argv[1], "boa", 3) == 0) {
+               int err = ft_board_setup(working_fdt, gd->bd);
+
+               if (err) {
+                       printf("Failed to update board information in FDT: %s\n",
+                              fdt_strerror(err));
+                       return CMD_RET_FAILURE;
+               }
+       }
+#endif
+#ifdef CONFIG_OF_SYSTEM_SETUP
+       /* Call the board-specific fixup routine */
+       else if (strncmp(argv[1], "sys", 3) == 0) {
+               int err = ft_system_setup(working_fdt, gd->bd);
+
+               if (err) {
+                       printf("Failed to add system information to FDT: %s\n",
+                              fdt_strerror(err));
+                       return CMD_RET_FAILURE;
+               }
+       }
 #endif
        /* Create a chosen node */
-       else if (argv[1][0] == 'c') {
+       else if (strncmp(argv[1], "cho", 3) == 0) {
                unsigned long initrd_start = 0, initrd_end = 0;
 
                if ((argc != 2) && (argc != 4))
@@ -582,12 +601,47 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        initrd_end = simple_strtoul(argv[3], NULL, 16);
                }
 
-               fdt_chosen(working_fdt, 1);
-               fdt_initrd(working_fdt, initrd_start, initrd_end, 1);
+               fdt_chosen(working_fdt);
+               fdt_initrd(working_fdt, initrd_start, initrd_end);
+
+#if defined(CONFIG_FIT_SIGNATURE)
+       } else if (strncmp(argv[1], "che", 3) == 0) {
+               int cfg_noffset;
+               int ret;
+               unsigned long addr;
+               struct fdt_header *blob;
+
+               if (!working_fdt)
+                       return CMD_RET_FAILURE;
+
+               if (argc > 2) {
+                       addr = simple_strtoul(argv[2], NULL, 16);
+                       blob = map_sysmem(addr, 0);
+               } else {
+                       blob = (struct fdt_header *)gd->fdt_blob;
+               }
+               if (!fdt_valid(&blob))
+                       return 1;
+
+               gd->fdt_blob = blob;
+               cfg_noffset = fit_conf_get_node(working_fdt, NULL);
+               if (!cfg_noffset) {
+                       printf("Could not find configuration node: %s\n",
+                              fdt_strerror(cfg_noffset));
+                       return CMD_RET_FAILURE;
+               }
+
+               ret = fit_config_verify(working_fdt, cfg_noffset);
+               if (ret == 0)
+                       return CMD_RET_SUCCESS;
+               else
+                       return CMD_RET_FAILURE;
+#endif
+
        }
        /* resize the fdt */
        else if (strncmp(argv[1], "re", 2) == 0) {
-               fdt_resize(working_fdt);
+               fdt_shrink_to_minimum(working_fdt);
        }
        else {
                /* Unrecognized command */
@@ -599,16 +653,23 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 /****************************************************************************/
 
-static int fdt_valid(void)
+/**
+ * fdt_valid() - Check if an FDT is valid. If not, change it to NULL
+ *
+ * @blobp: Pointer to FDT pointer
+ * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL)
+ */
+static int fdt_valid(struct fdt_header **blobp)
 {
-       int  err;
+       const void *blob = *blobp;
+       int err;
 
-       if (working_fdt == NULL) {
+       if (blob == NULL) {
                printf ("The address of the fdt is invalid (NULL).\n");
                return 0;
        }
 
-       err = fdt_check_header(working_fdt);
+       err = fdt_check_header(blob);
        if (err == 0)
                return 1;       /* valid */
 
@@ -618,23 +679,21 @@ static int fdt_valid(void)
                 * Be more informative on bad version.
                 */
                if (err == -FDT_ERR_BADVERSION) {
-                       if (fdt_version(working_fdt) <
+                       if (fdt_version(blob) <
                            FDT_FIRST_SUPPORTED_VERSION) {
                                printf (" - too old, fdt %d < %d",
-                                       fdt_version(working_fdt),
+                                       fdt_version(blob),
                                        FDT_FIRST_SUPPORTED_VERSION);
-                               working_fdt = NULL;
                        }
-                       if (fdt_last_comp_version(working_fdt) >
+                       if (fdt_last_comp_version(blob) >
                            FDT_LAST_SUPPORTED_VERSION) {
                                printf (" - too new, fdt %d > %d",
-                                       fdt_version(working_fdt),
+                                       fdt_version(blob),
                                        FDT_LAST_SUPPORTED_VERSION);
-                               working_fdt = NULL;
                        }
-                       return 0;
                }
                printf("\n");
+               *blobp = NULL;
                return 0;
        }
        return 1;
@@ -965,9 +1024,12 @@ static int fdt_print(const char *pathp, char *prop, int depth)
 /********************************************************************/
 #ifdef CONFIG_SYS_LONGHELP
 static char fdt_help_text[] =
-       "addr   <addr> [<length>]        - Set the fdt location to <addr>\n"
+       "addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>\n"
 #ifdef CONFIG_OF_BOARD_SETUP
        "fdt boardsetup                      - Do board-specific set up\n"
+#endif
+#ifdef CONFIG_OF_SYSTEM_SETUP
+       "fdt systemsetup                     - Do system-specific set up\n"
 #endif
        "fdt move   <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n"
        "fdt resize                          - Resize fdt to size + padding to 4k addr\n"
@@ -988,6 +1050,11 @@ static char fdt_help_text[] =
        "fdt rsvmem delete <index>           - Delete a mem reserves\n"
        "fdt chosen [<start> <end>]          - Add/update the /chosen branch in the tree\n"
        "                                        <start>/<end> - initrd start/end addr\n"
+#if defined(CONFIG_FIT_SIGNATURE)
+       "fdt checksign [<addr>]              - check FIT signature\n"
+       "                                        <start> - addr of key blob\n"
+       "                                                  default gd->fdt_blob\n"
+#endif
        "NOTE: Dereference aliases by omiting the leading '/', "
                "e.g. fdt print ethernet0.";
 #endif