Merge https://source.denx.de/u-boot/custodians/u-boot-spi
[platform/kernel/u-boot.git] / cmd / fdt.c
index b783b0d..2a207bf 100644 (file)
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -1,33 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2007
  * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
  * Based on code written by:
  *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
  *   Matthew McClintock <msm@freescale.com>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <command.h>
+#include <env.h>
+#include <image.h>
 #include <linux/ctype.h>
 #include <linux/types.h>
 #include <asm/global_data.h>
-#include <libfdt.h>
+#include <linux/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 */
-#define CMD_FDT_MAX_DUMP 64
 
 /*
  * Global data (for the gd->bd)
  */
 DECLARE_GLOBAL_DATA_PTR;
 
-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);
@@ -74,34 +73,62 @@ static int fdt_value_env_set(const void *nodep, int len, const char *var)
        return 0;
 }
 
+static const char * const fdt_member_table[] = {
+       "magic",
+       "totalsize",
+       "off_dt_struct",
+       "off_dt_strings",
+       "off_mem_rsvmap",
+       "version",
+       "last_comp_version",
+       "boot_cpuid_phys",
+       "size_dt_strings",
+       "size_dt_struct",
+};
+
+static int fdt_get_header_value(int argc, char *const argv[])
+{
+       fdt32_t *fdtp = (fdt32_t *)working_fdt;
+       ulong val;
+       int i;
+
+       if (argv[2][0] != 'g')
+               return CMD_RET_FAILURE;
+
+       for (i = 0; i < ARRAY_SIZE(fdt_member_table); i++) {
+               if (strcmp(fdt_member_table[i], argv[4]))
+                       continue;
+
+               val = fdt32_to_cpu(fdtp[i]);
+               env_set_hex(argv[3], val);
+               return CMD_RET_SUCCESS;
+       }
+
+       return CMD_RET_FAILURE;
+}
+
 /*
  * Flattened Device Tree command, see the help for parameter definitions.
  */
-static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
        if (argc < 2)
                return CMD_RET_USAGE;
 
-       /*
-        * Set the address of the fdt
-        */
+       /* fdt addr: Set the address of the fdt */
        if (strncmp(argv[1], "ad", 2) == 0) {
                unsigned long addr;
                int control = 0;
                struct fdt_header *blob;
-               /*
-                * Set the address [and length] of the fdt.
-                */
+
+               /* Set the address [and length] of the fdt */
                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;
@@ -109,13 +136,14 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                                blob = working_fdt;
                        if (!blob || !fdt_valid(&blob))
                                return 1;
-                       printf("The address of the fdt is %#08lx\n",
+                       printf("%s fdt: %08lx\n",
+                              control ? "Control" : "Working",
                               control ? (ulong)map_to_sysmem(blob) :
-                                       env_get_hex("fdtaddr", 0));
+                              env_get_hex("fdtaddr", 0));
                        return 0;
                }
 
-               addr = simple_strtoul(argv[0], NULL, 16);
+               addr = hextoul(argv[0], NULL);
                blob = map_sysmem(addr, 0);
                if (!fdt_valid(&blob))
                        return 1;
@@ -127,22 +155,18 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                if (argc >= 2) {
                        int  len;
                        int  err;
-                       /*
-                        * Optional new length
-                        */
-                       len = simple_strtoul(argv[1], NULL, 16);
+
+                       /* Optional new length */
+                       len = hextoul(argv[1], NULL);
                        if (len < fdt_totalsize(blob)) {
-                               printf ("New length %d < existing length %d, "
-                                       "ignoring.\n",
-                                       len, fdt_totalsize(blob));
+                               printf("New length %d < existing length %d, ignoring\n",
+                                      len, fdt_totalsize(blob));
                        } else {
-                               /*
-                                * Open in place with a new length.
-                                */
+                               /* Open in place with a new length */
                                err = fdt_open_into(blob, blob, len);
                                if (err != 0) {
-                                       printf ("libfdt fdt_open_into(): %s\n",
-                                               fdt_strerror(err));
+                                       printf("libfdt fdt_open_into(): %s\n",
+                                              fdt_strerror(err));
                                }
                        }
                }
@@ -151,10 +175,9 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        }
 
        if (!working_fdt) {
-               puts(
-                       "No FDT memory address configured. Please configure\n"
-                       "the FDT address via \"fdt addr <address>\" command.\n"
-                       "Aborting!\n");
+               puts("No FDT memory address configured. Please configure\n"
+                    "the FDT address via \"fdt addr <address>\" command.\n"
+                    "Aborting!\n");
                return CMD_RET_FAILURE;
        }
 
@@ -172,11 +195,11 @@ 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);
+               working_fdt = (struct fdt_header *)hextoul(argv[2], NULL);
                if (!fdt_valid(&working_fdt))
                        return 1;
 
-               newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
+               newaddr = (struct fdt_header *)hextoul(argv[3], NULL);
 
                /*
                 * If the user specifies a length, use that.  Otherwise use the
@@ -185,7 +208,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                if (argc <= 4) {
                        len = fdt_totalsize(working_fdt);
                } else {
-                       len = simple_strtoul(argv[4], NULL, 16);
+                       len = hextoul(argv[4], NULL);
                        if (len < fdt_totalsize(working_fdt)) {
                                printf ("New length 0x%X < existing length "
                                        "0x%X, aborting.\n",
@@ -203,7 +226,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                                fdt_strerror(err));
                        return 1;
                }
-               working_fdt = newaddr;
+               set_working_fdt_addr((ulong)newaddr);
 #ifdef CONFIG_OF_SYSTEM_SETUP
        /* Call the board-specific fixup routine */
        } else if (strncmp(argv[1], "sys", 3) == 0) {
@@ -252,7 +275,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        /*
         * Set the value of a property in the working_fdt.
         */
-       } else if (argv[1][0] == 's') {
+       } else if (strncmp(argv[1], "se", 2) == 0) {
                char *pathp;            /* path */
                char *prop;             /* property */
                int  nodeoffset;        /* node offset from libfdt */
@@ -341,21 +364,22 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                }
 
                if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) {
-                       int reqIndex = -1;
+                       int req_index = -1;
                        int startDepth = fdt_node_depth(
                                working_fdt, nodeoffset);
                        int curDepth = startDepth;
-                       int curIndex = -1;
+                       int cur_index = -1;
                        int nextNodeOffset = fdt_next_node(
                                working_fdt, nodeoffset, &curDepth);
 
                        if (subcmd[0] == 'n')
-                               reqIndex = simple_strtoul(argv[5], NULL, 16);
+                               req_index = hextoul(argv[5], NULL);
 
                        while (curDepth > startDepth) {
                                if (curDepth == startDepth + 1)
-                                       curIndex++;
-                               if (subcmd[0] == 'n' && curIndex == reqIndex) {
+                                       cur_index++;
+                               if (subcmd[0] == 'n' &&
+                                   cur_index == req_index) {
                                        const char *node_name;
 
                                        node_name = fdt_get_name(working_fdt,
@@ -371,7 +395,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 */
-                               env_set_ulong(var, curIndex + 1);
+                               env_set_ulong(var, cur_index + 1);
                        } else {
                                /* node index not found */
                                printf("libfdt node not found\n");
@@ -492,6 +516,9 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
         * Display header info
         */
        } else if (argv[1][0] == 'h') {
+               if (argc == 5)
+                       return fdt_get_header_value(argc, argv);
+
                u32 version = fdt_version(working_fdt);
                printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt));
                printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt),
@@ -522,7 +549,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
         * Set boot cpu id
         */
        } else if (strncmp(argv[1], "boo", 3) == 0) {
-               unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
+               unsigned long tmp = hextoul(argv[2], NULL);
                fdt_set_boot_cpuid_phys(working_fdt, tmp);
 
        /*
@@ -574,7 +601,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                                return err;
                        }
                } else if (argv[2][0] == 'd') {
-                       unsigned long idx = simple_strtoul(argv[3], NULL, 16);
+                       unsigned long idx = hextoul(argv[3], NULL);
                        int err = fdt_del_mem_rsv(working_fdt, idx);
 
                        if (err < 0) {
@@ -597,6 +624,9 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                               fdt_strerror(err));
                        return CMD_RET_FAILURE;
                }
+#ifdef CONFIG_ARCH_KEYSTONE
+               ft_board_setup_ex(working_fdt, gd->bd);
+#endif
        }
 #endif
        /* Create a chosen node */
@@ -607,8 +637,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        return CMD_RET_USAGE;
 
                if (argc == 4) {
-                       initrd_start = simple_strtoul(argv[2], NULL, 16);
-                       initrd_end = simple_strtoul(argv[3], NULL, 16);
+                       initrd_start = hextoul(argv[2], NULL);
+                       initrd_end = hextoul(argv[3], NULL);
                }
 
                fdt_chosen(working_fdt);
@@ -625,7 +655,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        return CMD_RET_FAILURE;
 
                if (argc > 2) {
-                       addr = simple_strtoul(argv[2], NULL, 16);
+                       addr = hextoul(argv[2], NULL);
                        blob = map_sysmem(addr, 0);
                } else {
                        blob = (struct fdt_header *)gd->fdt_blob;
@@ -662,7 +692,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                if (!working_fdt)
                        return CMD_RET_FAILURE;
 
-               addr = simple_strtoul(argv[2], NULL, 16);
+               addr = hextoul(argv[2], NULL);
                blob = map_sysmem(addr, 0);
                if (!fdt_valid(&blob))
                        return CMD_RET_FAILURE;
@@ -677,7 +707,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        else if (strncmp(argv[1], "re", 2) == 0) {
                uint extrasize;
                if (argc > 2)
-                       extrasize = simple_strtoul(argv[2], NULL, 16);
+                       extrasize = hextoul(argv[2], NULL);
                else
                        extrasize = 0;
                fdt_shrink_to_minimum(working_fdt, extrasize);
@@ -692,54 +722,6 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 /****************************************************************************/
 
-/**
- * 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)
-{
-       const void *blob = *blobp;
-       int err;
-
-       if (blob == NULL) {
-               printf ("The address of the fdt is invalid (NULL).\n");
-               return 0;
-       }
-
-       err = fdt_check_header(blob);
-       if (err == 0)
-               return 1;       /* valid */
-
-       if (err < 0) {
-               printf("libfdt fdt_check_header(): %s", fdt_strerror(err));
-               /*
-                * Be more informative on bad version.
-                */
-               if (err == -FDT_ERR_BADVERSION) {
-                       if (fdt_version(blob) <
-                           FDT_FIRST_SUPPORTED_VERSION) {
-                               printf (" - too old, fdt %d < %d",
-                                       fdt_version(blob),
-                                       FDT_FIRST_SUPPORTED_VERSION);
-                       }
-                       if (fdt_last_comp_version(blob) >
-                           FDT_LAST_SUPPORTED_VERSION) {
-                               printf (" - too new, fdt %d > %d",
-                                       fdt_version(blob),
-                                       FDT_LAST_SUPPORTED_VERSION);
-                       }
-               }
-               printf("\n");
-               *blobp = NULL;
-               return 0;
-       }
-       return 1;
-}
-
-/****************************************************************************/
-
 /*
  * Parse the user's input, partially heuristic.  Valid formats:
  * <0x00112233 4 05>   - an array of cells.  Numbers follow standard
@@ -816,7 +798,7 @@ static int fdt_parse_prop(char * const *newval, int count, char *data, int *len)
                        }
                        if (!isxdigit(*newp))
                                break;
-                       tmp = simple_strtoul(newp, &newp, 16);
+                       tmp = hextoul(newp, &newp);
                        *data++ = tmp & 0xFF;
                        *len    = *len + 1;
                }
@@ -893,11 +875,17 @@ static int is_printable_string(const void *data, int len)
 static void print_data(const void *data, int len)
 {
        int j;
+       const char *env_max_dump;
+       ulong max_dump = ULONG_MAX;
 
        /* no data, don't print */
        if (len == 0)
                return;
 
+       env_max_dump = env_get("fdt_max_dump");
+       if (env_max_dump)
+               max_dump = hextoul(env_max_dump, NULL);
+
        /*
         * It is a string, but it may have multiple strings (embedded '\0's).
         */
@@ -916,7 +904,7 @@ static void print_data(const void *data, int len)
        }
 
        if ((len %4) == 0) {
-               if (len > CMD_FDT_MAX_DUMP)
+               if (len > max_dump)
                        printf("* 0x%p [0x%08x]", data, len);
                else {
                        const __be32 *p;
@@ -928,7 +916,7 @@ static void print_data(const void *data, int len)
                        printf(">");
                }
        } else { /* anything else... hexdump */
-               if (len > CMD_FDT_MAX_DUMP)
+               if (len > max_dump)
                        printf("* 0x%p [0x%08x]", data, len);
                else {
                        const u8 *s;
@@ -1088,7 +1076,8 @@ static char fdt_help_text[] =
        "fdt set    <path> <prop> [<val>]    - Set <property> [to <val>]\n"
        "fdt mknode <path> <node>            - Create a new node after <path>\n"
        "fdt rm     <path> [<prop>]          - Delete the node or <property>\n"
-       "fdt header                          - Display header info\n"
+       "fdt header [get <var> <member>]     - Display header info\n"
+       "                                      get - get header member <member> and store it in <var>\n"
        "fdt bootcpu <id>                    - Set boot cpuid\n"
        "fdt memory <addr> <size>            - Add/Update memory node\n"
        "fdt rsvmem print                    - Show current mem reserves\n"