Merge branch 'master' of git://git.denx.de/u-boot-blackfin
[platform/kernel/u-boot.git] / common / image.c
index c86b86f..f175541 100644 (file)
@@ -141,6 +141,7 @@ static const table_entry_t uimage_type[] = {
        {       IH_TYPE_FLATDT,     "flat_dt",    "Flat Device Tree",   },
        {       IH_TYPE_KWBIMAGE,   "kwbimage",   "Kirkwood Boot Image",},
        {       IH_TYPE_IMXIMAGE,   "imximage",   "Freescale i.MX Boot Image",},
+       {       IH_TYPE_UBLIMAGE,   "ublimage",   "Davinci UBL image",},
        {       -1,                 "",           "",                   },
 };
 
@@ -454,6 +455,22 @@ phys_size_t getenv_bootm_size(void)
 #endif
 }
 
+phys_size_t getenv_bootm_mapsize(void)
+{
+       phys_size_t tmp;
+       char *s = getenv ("bootm_mapsize");
+       if (s) {
+               tmp = (phys_size_t)simple_strtoull (s, NULL, 16);
+               return tmp;
+       }
+
+#if defined(CONFIG_SYS_BOOTMAPSZ)
+       return CONFIG_SYS_BOOTMAPSZ;
+#else
+       return getenv_bootm_size();
+#endif
+}
+
 void memmove_wd (void *to, void *from, size_t len, ulong chunksz)
 {
        if (to == from)
@@ -1169,6 +1186,34 @@ static int fit_check_fdt (const void *fit, int fdt_noffset, int verify)
 #define CONFIG_SYS_FDT_PAD 0x3000
 #endif
 
+#if defined(CONFIG_OF_LIBFDT)
+/**
+ * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable
+ * @lmb: pointer to lmb handle, will be used for memory mgmt
+ * @fdt_blob: pointer to fdt blob base address
+ *
+ * Adds the memreserve regions in the dtb to the lmb block.  Adding the
+ * memreserve regions prevents u-boot from using them to store the initrd
+ * or the fdt blob.
+ */
+void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob)
+{
+       uint64_t addr, size;
+       int i, total;
+
+       if (fdt_check_header (fdt_blob) != 0)
+               return;
+
+       total = fdt_num_mem_rsv(fdt_blob);
+       for (i = 0; i < total; i++) {
+               if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0)
+                       continue;
+               printf("   reserving fdt memory region: addr=%llx size=%llx\n",
+                       (unsigned long long)addr, (unsigned long long)size);
+               lmb_reserve(lmb, addr, size);
+       }
+}
+
 /**
  * boot_relocate_fdt - relocate flat device tree
  * @lmb: pointer to lmb handle, will be used for memory mgmt
@@ -1186,13 +1231,14 @@ static int fit_check_fdt (const void *fit, int fdt_noffset, int verify)
  *      0 - success
  *      1 - failure
  */
-#if defined(CONFIG_SYS_BOOTMAPSZ)
 int boot_relocate_fdt (struct lmb *lmb, char **of_flat_tree, ulong *of_size)
 {
        void    *fdt_blob = *of_flat_tree;
        void    *of_start = 0;
+       char    *fdt_high;
        ulong   of_len = 0;
        int     err;
+       int     disable_relocation = 0;
 
        /* nothing to do */
        if (*of_size == 0)
@@ -1206,26 +1252,62 @@ int boot_relocate_fdt (struct lmb *lmb, char **of_flat_tree, ulong *of_size)
        /* position on a 4K boundary before the alloc_current */
        /* Pad the FDT by a specified amount */
        of_len = *of_size + CONFIG_SYS_FDT_PAD;
-       of_start = (void *)(unsigned long)lmb_alloc_base(lmb, of_len, 0x1000,
-                       CONFIG_SYS_BOOTMAPSZ + getenv_bootm_low());
+
+       /* If fdt_high is set use it to select the relocation address */
+       fdt_high = getenv("fdt_high");
+       if (fdt_high) {
+               void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16);
+
+               if (((ulong) desired_addr) == ~0UL) {
+                       /* All ones means use fdt in place */
+                       desired_addr = fdt_blob;
+                       disable_relocation = 1;
+               }
+               if (desired_addr) {
+                       of_start =
+                           (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
+                                                          ((ulong)
+                                                           desired_addr)
+                                                          + of_len);
+                       if (desired_addr && of_start != desired_addr) {
+                               puts("Failed using fdt_high value for Device Tree");
+                               goto error;
+                       }
+               } else {
+                       of_start =
+                           (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000);
+               }
+       } else {
+               of_start =
+                   (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000,
+                                                  getenv_bootm_mapsize()
+                                                  + getenv_bootm_low());
+       }
 
        if (of_start == 0) {
                puts("device tree - allocation error\n");
                goto error;
        }
 
-       debug ("## device tree at %p ... %p (len=%ld [0x%lX])\n",
-               fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);
+       if (disable_relocation) {
+               /* We assume there is space after the existing fdt to use for padding */
+               fdt_set_totalsize(of_start, of_len);
+               printf("   Using Device Tree in place at %p, end %p\n",
+                      of_start, of_start + of_len - 1);
+       } else {
+               debug ("## device tree at %p ... %p (len=%ld [0x%lX])\n",
+                       fdt_blob, fdt_blob + *of_size - 1, of_len, of_len);
 
-       printf ("   Loading Device Tree to %p, end %p ... ",
-               of_start, of_start + of_len - 1);
+               printf ("   Loading Device Tree to %p, end %p ... ",
+                       of_start, of_start + of_len - 1);
 
-       err = fdt_open_into (fdt_blob, of_start, of_len);
-       if (err != 0) {
-               fdt_error ("fdt move failed");
-               goto error;
+               err = fdt_open_into (fdt_blob, of_start, of_len);
+               if (err != 0) {
+                       fdt_error ("fdt move failed");
+                       goto error;
+               }
+               puts ("OK\n");
        }
-       puts ("OK\n");
 
        *of_flat_tree = of_start;
        *of_size = of_len;
@@ -1236,7 +1318,7 @@ int boot_relocate_fdt (struct lmb *lmb, char **of_flat_tree, ulong *of_size)
 error:
        return 1;
 }
-#endif /* CONFIG_SYS_BOOTMAPSZ */
+#endif /* CONFIG_OF_LIBFDT */
 
 /**
  * boot_get_fdt - main fdt handling routine
@@ -1581,7 +1663,7 @@ int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end)
        char *s;
 
        cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf,
-                                    CONFIG_SYS_BOOTMAPSZ + getenv_bootm_low());
+                               getenv_bootm_mapsize() + getenv_bootm_low());
 
        if (cmdline == NULL)
                return -1;
@@ -1617,7 +1699,7 @@ int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end)
 int boot_get_kbd (struct lmb *lmb, bd_t **kbd)
 {
        *kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf,
-                                    CONFIG_SYS_BOOTMAPSZ + getenv_bootm_low());
+                               getenv_bootm_mapsize() + getenv_bootm_low());
        if (*kbd == NULL)
                return -1;