]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/image.c
[new uImage] Factor out common image_get_ramdisk() routine
[karo-tx-uboot.git] / common / image.c
index 6726f0370b738a3ec79e2f2046a1e6c59d220ae0..e4be4caf856eb8648dc2bee405fd43050748b198 100644 (file)
  * MA 02111-1307 USA
  */
 #ifndef USE_HOSTCC
-# include <common.h>
-# include <watchdog.h>
+#include <common.h>
+#include <watchdog.h>
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+#include <status_led.h>
+#endif
+
+#ifdef CONFIG_HAS_DATAFLASH
+#include <dataflash.h>
+#endif
+
+extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
 #else
-# include "mkimage.h"
+#include "mkimage.h"
 #endif
 
 #include <image.h>
@@ -280,4 +290,191 @@ const char* image_get_comp_name (uint8_t comp)
 
        return name;
 }
+
+/**
+ * image_get_ramdisk - get and verify ramdisk image
+ * @cmdtp: command table pointer
+ * @flag: command flag
+ * @argc: command argument count
+ * @argv: command argument list
+ * @rd_addr: ramdisk image start address
+ * @arch: expected ramdisk architecture
+ * @verify: checksum verification flag
+ *
+ * image_get_ramdisk() returns a pointer to the verified ramdisk image
+ * header. Routine receives image start address and expected architecture
+ * flag. Verification done covers data and header integrity and os/type/arch
+ * fields checking.
+ *
+ * If dataflash support is enabled routine checks for dataflash addresses
+ * and handles required dataflash reads.
+ *
+ * returns:
+ *     pointer to a ramdisk image header, if image was found and valid
+ *     otherwise, board is reset
+ */
+image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag,
+               int argc, char *argv[],
+               ulong rd_addr, uint8_t arch, int verify)
+{
+       image_header_t *rd_hdr;
+
+       show_boot_progress (9);
+
+#ifdef CONFIG_HAS_DATAFLASH
+       if (addr_dataflash (rd_addr)) {
+               rd_hdr = (image_header_t *)CFG_LOAD_ADDR;
+               debug ("   Reading Ramdisk image header from dataflash address "
+                       "%08lx to %08lx\n", rd_addr, (ulong)rd_hdr);
+               read_dataflash (rd_addr, image_get_header_size (),
+                               (char *)rd_hdr);
+       } else
+#endif
+       rd_hdr = (image_header_t *)rd_addr;
+
+       if (!image_check_magic (rd_hdr)) {
+               puts ("Bad Magic Number\n");
+               show_boot_progress (-10);
+               do_reset (cmdtp, flag, argc, argv);
+       }
+
+       if (!image_check_hcrc (rd_hdr)) {
+               puts ("Bad Header Checksum\n");
+               show_boot_progress (-11);
+               do_reset (cmdtp, flag, argc, argv);
+       }
+
+       show_boot_progress (10);
+       print_image_hdr (rd_hdr);
+
+#ifdef CONFIG_HAS_DATAFLASH
+       if (addr_dataflash (rd_addr)) {
+               debug ("   Reading Ramdisk image data from dataflash address "
+                       "%08lx to %08lx\n", rd_addr + image_get_header_size,
+                       (ulong)image_get_data (rd_hdr));
+
+               read_dataflash (rd_addr + image_get_header_size (),
+                               image_get_data_size (rd_hdr),
+                               (char *)image_get_data (rd_hdr));
+       }
 #endif
+
+       if (verify) {
+               puts("   Verifying Checksum ... ");
+               if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) {
+                       puts ("Bad Data CRC\n");
+                       show_boot_progress (-12);
+                       do_reset (cmdtp, flag, argc, argv);
+               }
+               puts("OK\n");
+       }
+
+       show_boot_progress (11);
+
+       if (!image_check_os (rd_hdr, IH_OS_LINUX) ||
+           !image_check_arch (rd_hdr, arch) ||
+           !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) {
+               printf ("No Linux %s Ramdisk Image\n",
+                               image_get_arch_name(arch));
+               show_boot_progress (-13);
+               do_reset (cmdtp, flag, argc, argv);
+       }
+
+       return rd_hdr;
+}
+
+/**
+ * get_ramdisk - main ramdisk handling routine
+ * @cmdtp: command table pointer
+ * @flag: command flag
+ * @argc: command argument count
+ * @argv: command argument list
+ * @hdr: pointer to the posiibly multi componet kernel image
+ * @verify: checksum verification flag
+ * @arch: expected ramdisk architecture
+ * @rd_start: pointer to a ulong variable, will hold ramdisk start address
+ * @rd_end: pointer to a ulong variable, will hold ramdisk end
+ *
+ * get_ramdisk() is responsible for finding a valid ramdisk image.
+ * Curently supported are the following ramdisk sources:
+ *      - multicomponent kernel/ramdisk image,
+ *      - commandline provided address of decicated ramdisk image.
+ *
+ * returns:
+ *     rd_start and rd_end are set to ramdisk start/end addresses if
+ *     ramdisk image is found and valid
+ *     rd_start and rd_end are set to 0 if no ramdisk exists
+ *     board is reset if ramdisk image is found but corrupted
+ */
+void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
+               image_header_t *hdr, int verify, uint8_t arch,
+               ulong *rd_start, ulong *rd_end)
+{
+       ulong rd_addr;
+       ulong rd_data, rd_len;
+       image_header_t *rd_hdr;
+
+       if (argc >= 3) {
+               /*
+                * Look for a '-' which indicates to ignore the
+                * ramdisk argument
+                */
+               if (strcmp(argv[2], "-") ==  0) {
+                       debug ("## Skipping init Ramdisk\n");
+                       rd_len = rd_data = 0;
+               } else {
+                       /*
+                        * Check if there is an initrd image at the
+                        * address provided in the second bootm argument
+                        */
+                       rd_addr = simple_strtoul (argv[2], NULL, 16);
+                       printf ("## Loading init Ramdisk Image at %08lx ...\n",
+                                       rd_addr);
+
+                       rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv,
+                                               rd_addr, arch, verify);
+
+                       rd_data = image_get_data (rd_hdr);
+                       rd_len = image_get_data_size (rd_hdr);
+
+#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
+                       /*
+                        *we need to copy the ramdisk to SRAM to let Linux boot
+                        */
+                       memmove ((void *)image_get_load (rd_hdr),
+                                       (uchar *)rd_data, rd_len);
+
+                       rd_data = image_get_load (rd_hdr);
+#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */
+               }
+
+       } else if (image_check_type (hdr, IH_TYPE_MULTI)) {
+               /*
+                * Now check if we have a multifile image
+                * Get second entry data start address and len
+                */
+               show_boot_progress (13);
+               printf ("## Loading init Ramdisk from multi component "
+                               "Image at %08lx ...\n", (ulong)hdr);
+               image_multi_getimg (hdr, 1, &rd_data, &rd_len);
+       } else {
+               /*
+                * no initrd image
+                */
+               show_boot_progress (14);
+               rd_len = rd_data = 0;
+       }
+
+       if (!rd_data) {
+               debug ("## No init Ramdisk\n");
+               *rd_start = 0;
+               *rd_end = 0;
+       } else {
+               *rd_start = rd_data;
+               *rd_end = rd_data + rd_len;
+       }
+       debug ("   ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n",
+                       *rd_start, *rd_end);
+}
+#endif /* USE_HOSTCC */
+