summaryrefslogtreecommitdiffstats
path: root/common/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/image.c')
-rw-r--r--common/image.c203
1 files changed, 200 insertions, 3 deletions
diff --git a/common/image.c b/common/image.c
index 6726f0370b..e4be4caf85 100644
--- a/common/image.c
+++ b/common/image.c
@@ -23,10 +23,20 @@
* 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 */
+