1b97a2a0aSMarian Balakowicz /* 2b97a2a0aSMarian Balakowicz * (C) Copyright 2008 Semihalf 3b97a2a0aSMarian Balakowicz * 4b97a2a0aSMarian Balakowicz * (C) Copyright 2000-2006 5b97a2a0aSMarian Balakowicz * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 6b97a2a0aSMarian Balakowicz * 7b97a2a0aSMarian Balakowicz * See file CREDITS for list of people who contributed to this 8b97a2a0aSMarian Balakowicz * project. 9b97a2a0aSMarian Balakowicz * 10b97a2a0aSMarian Balakowicz * This program is free software; you can redistribute it and/or 11b97a2a0aSMarian Balakowicz * modify it under the terms of the GNU General Public License as 12b97a2a0aSMarian Balakowicz * published by the Free Software Foundation; either version 2 of 13b97a2a0aSMarian Balakowicz * the License, or (at your option) any later version. 14b97a2a0aSMarian Balakowicz * 15b97a2a0aSMarian Balakowicz * This program is distributed in the hope that it will be useful, 16b97a2a0aSMarian Balakowicz * but WITHOUT ANY WARRANTY; without even the implied warranty of 17b97a2a0aSMarian Balakowicz * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18b97a2a0aSMarian Balakowicz * GNU General Public License for more details. 19b97a2a0aSMarian Balakowicz * 20b97a2a0aSMarian Balakowicz * You should have received a copy of the GNU General Public License 21b97a2a0aSMarian Balakowicz * along with this program; if not, write to the Free Software 22b97a2a0aSMarian Balakowicz * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23b97a2a0aSMarian Balakowicz * MA 02111-1307 USA 24b97a2a0aSMarian Balakowicz */ 25ceaed2b1SMarian Balakowicz 26ceaed2b1SMarian Balakowicz #define DEBUG 27ceaed2b1SMarian Balakowicz 28b97a2a0aSMarian Balakowicz #ifndef USE_HOSTCC 29b97a2a0aSMarian Balakowicz #include <common.h> 30b97a2a0aSMarian Balakowicz #include <watchdog.h> 315ad03eb3SMarian Balakowicz 325ad03eb3SMarian Balakowicz #ifdef CONFIG_SHOW_BOOT_PROGRESS 335ad03eb3SMarian Balakowicz #include <status_led.h> 345ad03eb3SMarian Balakowicz #endif 355ad03eb3SMarian Balakowicz 365ad03eb3SMarian Balakowicz #ifdef CONFIG_HAS_DATAFLASH 375ad03eb3SMarian Balakowicz #include <dataflash.h> 385ad03eb3SMarian Balakowicz #endif 395ad03eb3SMarian Balakowicz 40ceaed2b1SMarian Balakowicz #ifdef CONFIG_LOGBUFFER 41ceaed2b1SMarian Balakowicz #include <logbuff.h> 42ceaed2b1SMarian Balakowicz #endif 43ceaed2b1SMarian Balakowicz 442242f536SMarian Balakowicz #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) 452242f536SMarian Balakowicz #include <rtc.h> 462242f536SMarian Balakowicz #endif 472242f536SMarian Balakowicz 48fff888a1SMarian Balakowicz #if defined(CONFIG_FIT) 49fff888a1SMarian Balakowicz #include <fdt.h> 50fff888a1SMarian Balakowicz #include <libfdt.h> 51fff888a1SMarian Balakowicz #include <fdt_support.h> 52fff888a1SMarian Balakowicz #endif 53fff888a1SMarian Balakowicz 54b6b0fe64SMarian Balakowicz #ifdef CONFIG_CMD_BDI 55b6b0fe64SMarian Balakowicz extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); 56b6b0fe64SMarian Balakowicz #endif 57b6b0fe64SMarian Balakowicz 58b6b0fe64SMarian Balakowicz DECLARE_GLOBAL_DATA_PTR; 598a5ea3e6SMarian Balakowicz 608a5ea3e6SMarian Balakowicz static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, 618a5ea3e6SMarian Balakowicz int argc, char *argv[], 628a5ea3e6SMarian Balakowicz ulong rd_addr, uint8_t arch, int verify); 63b97a2a0aSMarian Balakowicz #else 64b97a2a0aSMarian Balakowicz #include "mkimage.h" 65b6b0fe64SMarian Balakowicz #endif /* USE_HOSTCC*/ 66b97a2a0aSMarian Balakowicz 67b97a2a0aSMarian Balakowicz #include <image.h> 68b97a2a0aSMarian Balakowicz 69b97a2a0aSMarian Balakowicz unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); 70b97a2a0aSMarian Balakowicz 71b97a2a0aSMarian Balakowicz int image_check_hcrc (image_header_t *hdr) 72b97a2a0aSMarian Balakowicz { 73b97a2a0aSMarian Balakowicz ulong hcrc; 74b97a2a0aSMarian Balakowicz ulong len = image_get_header_size (); 75b97a2a0aSMarian Balakowicz image_header_t header; 76b97a2a0aSMarian Balakowicz 77b97a2a0aSMarian Balakowicz /* Copy header so we can blank CRC field for re-calculation */ 78b97a2a0aSMarian Balakowicz memmove (&header, (char *)hdr, image_get_header_size ()); 79b97a2a0aSMarian Balakowicz image_set_hcrc (&header, 0); 80b97a2a0aSMarian Balakowicz 81b97a2a0aSMarian Balakowicz hcrc = crc32 (0, (unsigned char *)&header, len); 82b97a2a0aSMarian Balakowicz 83b97a2a0aSMarian Balakowicz return (hcrc == image_get_hcrc (hdr)); 84b97a2a0aSMarian Balakowicz } 85b97a2a0aSMarian Balakowicz 86b97a2a0aSMarian Balakowicz int image_check_dcrc (image_header_t *hdr) 87b97a2a0aSMarian Balakowicz { 88b97a2a0aSMarian Balakowicz ulong data = image_get_data (hdr); 89b97a2a0aSMarian Balakowicz ulong len = image_get_data_size (hdr); 90b97a2a0aSMarian Balakowicz ulong dcrc = crc32 (0, (unsigned char *)data, len); 91b97a2a0aSMarian Balakowicz 92b97a2a0aSMarian Balakowicz return (dcrc == image_get_dcrc (hdr)); 93b97a2a0aSMarian Balakowicz } 94b97a2a0aSMarian Balakowicz 95af13cdbcSMarian Balakowicz #ifndef USE_HOSTCC 96b97a2a0aSMarian Balakowicz int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) 97b97a2a0aSMarian Balakowicz { 98b97a2a0aSMarian Balakowicz ulong dcrc = 0; 99b97a2a0aSMarian Balakowicz ulong len = image_get_data_size (hdr); 100b97a2a0aSMarian Balakowicz ulong data = image_get_data (hdr); 101b97a2a0aSMarian Balakowicz 102b97a2a0aSMarian Balakowicz #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 103b97a2a0aSMarian Balakowicz ulong cdata = data; 104b97a2a0aSMarian Balakowicz ulong edata = cdata + len; 105b97a2a0aSMarian Balakowicz 106b97a2a0aSMarian Balakowicz while (cdata < edata) { 107b97a2a0aSMarian Balakowicz ulong chunk = edata - cdata; 108b97a2a0aSMarian Balakowicz 109b97a2a0aSMarian Balakowicz if (chunk > chunksz) 110b97a2a0aSMarian Balakowicz chunk = chunksz; 111b97a2a0aSMarian Balakowicz dcrc = crc32 (dcrc, (unsigned char *)cdata, chunk); 112b97a2a0aSMarian Balakowicz cdata += chunk; 113b97a2a0aSMarian Balakowicz 114b97a2a0aSMarian Balakowicz WATCHDOG_RESET (); 115b97a2a0aSMarian Balakowicz } 116b97a2a0aSMarian Balakowicz #else 117b97a2a0aSMarian Balakowicz dcrc = crc32 (0, (unsigned char *)data, len); 118b97a2a0aSMarian Balakowicz #endif 119b97a2a0aSMarian Balakowicz 120b97a2a0aSMarian Balakowicz return (dcrc == image_get_dcrc (hdr)); 121b97a2a0aSMarian Balakowicz } 122b97a2a0aSMarian Balakowicz 123b97a2a0aSMarian Balakowicz int getenv_verify (void) 124b97a2a0aSMarian Balakowicz { 125b97a2a0aSMarian Balakowicz char *s = getenv ("verify"); 126b97a2a0aSMarian Balakowicz return (s && (*s == 'n')) ? 0 : 1; 127b97a2a0aSMarian Balakowicz } 128af13cdbcSMarian Balakowicz 129af13cdbcSMarian Balakowicz void memmove_wd (void *to, void *from, size_t len, ulong chunksz) 130af13cdbcSMarian Balakowicz { 131af13cdbcSMarian Balakowicz #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 132af13cdbcSMarian Balakowicz while (len > 0) { 133af13cdbcSMarian Balakowicz size_t tail = (len > chunksz) ? chunksz : len; 134af13cdbcSMarian Balakowicz WATCHDOG_RESET (); 135af13cdbcSMarian Balakowicz memmove (to, from, tail); 136af13cdbcSMarian Balakowicz to += tail; 137af13cdbcSMarian Balakowicz from += tail; 138af13cdbcSMarian Balakowicz len -= tail; 139af13cdbcSMarian Balakowicz } 140af13cdbcSMarian Balakowicz #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ 141af13cdbcSMarian Balakowicz memmove (to, from, len); 142af13cdbcSMarian Balakowicz #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ 143af13cdbcSMarian Balakowicz } 144af13cdbcSMarian Balakowicz #endif /* USE_HOSTCC */ 145f13e7b2eSMarian Balakowicz 146f13e7b2eSMarian Balakowicz /** 147f13e7b2eSMarian Balakowicz * image_multi_count - get component (sub-image) count 148f13e7b2eSMarian Balakowicz * @hdr: pointer to the header of the multi component image 149f13e7b2eSMarian Balakowicz * 150f13e7b2eSMarian Balakowicz * image_multi_count() returns number of components in a multi 151f13e7b2eSMarian Balakowicz * component image. 152f13e7b2eSMarian Balakowicz * 153f13e7b2eSMarian Balakowicz * Note: no checking of the image type is done, caller must pass 154f13e7b2eSMarian Balakowicz * a valid multi component image. 155f13e7b2eSMarian Balakowicz * 156f13e7b2eSMarian Balakowicz * returns: 157f13e7b2eSMarian Balakowicz * number of components 158f13e7b2eSMarian Balakowicz */ 159f13e7b2eSMarian Balakowicz ulong image_multi_count (image_header_t *hdr) 160f13e7b2eSMarian Balakowicz { 161f13e7b2eSMarian Balakowicz ulong i, count = 0; 162f13e7b2eSMarian Balakowicz ulong *size; 163f13e7b2eSMarian Balakowicz 164f13e7b2eSMarian Balakowicz /* get start of the image payload, which in case of multi 165f13e7b2eSMarian Balakowicz * component images that points to a table of component sizes */ 166f13e7b2eSMarian Balakowicz size = (ulong *)image_get_data (hdr); 167f13e7b2eSMarian Balakowicz 168f13e7b2eSMarian Balakowicz /* count non empty slots */ 169f13e7b2eSMarian Balakowicz for (i = 0; size[i]; ++i) 170f13e7b2eSMarian Balakowicz count++; 171f13e7b2eSMarian Balakowicz 172f13e7b2eSMarian Balakowicz return count; 173f13e7b2eSMarian Balakowicz } 174f13e7b2eSMarian Balakowicz 175f13e7b2eSMarian Balakowicz /** 176f13e7b2eSMarian Balakowicz * image_multi_getimg - get component data address and size 177f13e7b2eSMarian Balakowicz * @hdr: pointer to the header of the multi component image 178f13e7b2eSMarian Balakowicz * @idx: index of the requested component 179f13e7b2eSMarian Balakowicz * @data: pointer to a ulong variable, will hold component data address 180f13e7b2eSMarian Balakowicz * @len: pointer to a ulong variable, will hold component size 181f13e7b2eSMarian Balakowicz * 182f13e7b2eSMarian Balakowicz * image_multi_getimg() returns size and data address for the requested 183f13e7b2eSMarian Balakowicz * component in a multi component image. 184f13e7b2eSMarian Balakowicz * 185f13e7b2eSMarian Balakowicz * Note: no checking of the image type is done, caller must pass 186f13e7b2eSMarian Balakowicz * a valid multi component image. 187f13e7b2eSMarian Balakowicz * 188f13e7b2eSMarian Balakowicz * returns: 189f13e7b2eSMarian Balakowicz * data address and size of the component, if idx is valid 190f13e7b2eSMarian Balakowicz * 0 in data and len, if idx is out of range 191f13e7b2eSMarian Balakowicz */ 192f13e7b2eSMarian Balakowicz void image_multi_getimg (image_header_t *hdr, ulong idx, 193f13e7b2eSMarian Balakowicz ulong *data, ulong *len) 194f13e7b2eSMarian Balakowicz { 195f13e7b2eSMarian Balakowicz int i; 196f13e7b2eSMarian Balakowicz ulong *size; 197f13e7b2eSMarian Balakowicz ulong offset, tail, count, img_data; 198f13e7b2eSMarian Balakowicz 199f13e7b2eSMarian Balakowicz /* get number of component */ 200f13e7b2eSMarian Balakowicz count = image_multi_count (hdr); 201f13e7b2eSMarian Balakowicz 202f13e7b2eSMarian Balakowicz /* get start of the image payload, which in case of multi 203f13e7b2eSMarian Balakowicz * component images that points to a table of component sizes */ 204f13e7b2eSMarian Balakowicz size = (ulong *)image_get_data (hdr); 205f13e7b2eSMarian Balakowicz 206f13e7b2eSMarian Balakowicz /* get address of the proper component data start, which means 207f13e7b2eSMarian Balakowicz * skipping sizes table (add 1 for last, null entry) */ 208f13e7b2eSMarian Balakowicz img_data = image_get_data (hdr) + (count + 1) * sizeof (ulong); 209f13e7b2eSMarian Balakowicz 210f13e7b2eSMarian Balakowicz if (idx < count) { 211f13e7b2eSMarian Balakowicz *len = size[idx]; 212f13e7b2eSMarian Balakowicz offset = 0; 213f13e7b2eSMarian Balakowicz tail = 0; 214f13e7b2eSMarian Balakowicz 215f13e7b2eSMarian Balakowicz /* go over all indices preceding requested component idx */ 216f13e7b2eSMarian Balakowicz for (i = 0; i < idx; i++) { 217f13e7b2eSMarian Balakowicz /* add up i-th component size */ 218f13e7b2eSMarian Balakowicz offset += size[i]; 219f13e7b2eSMarian Balakowicz 220f13e7b2eSMarian Balakowicz /* add up alignment for i-th component */ 221f13e7b2eSMarian Balakowicz tail += (4 - size[i] % 4); 222f13e7b2eSMarian Balakowicz } 223f13e7b2eSMarian Balakowicz 224f13e7b2eSMarian Balakowicz /* calculate idx-th component data address */ 225f13e7b2eSMarian Balakowicz *data = img_data + offset + tail; 226f13e7b2eSMarian Balakowicz } else { 227f13e7b2eSMarian Balakowicz *len = 0; 228f13e7b2eSMarian Balakowicz *data = 0; 229f13e7b2eSMarian Balakowicz } 230f13e7b2eSMarian Balakowicz } 23142b73e8eSMarian Balakowicz 23242b73e8eSMarian Balakowicz #ifndef USE_HOSTCC 23342b73e8eSMarian Balakowicz const char* image_get_os_name (uint8_t os) 23442b73e8eSMarian Balakowicz { 23542b73e8eSMarian Balakowicz const char *name; 23642b73e8eSMarian Balakowicz 23742b73e8eSMarian Balakowicz switch (os) { 23842b73e8eSMarian Balakowicz case IH_OS_INVALID: name = "Invalid OS"; break; 23942b73e8eSMarian Balakowicz case IH_OS_NETBSD: name = "NetBSD"; break; 24042b73e8eSMarian Balakowicz case IH_OS_LINUX: name = "Linux"; break; 24142b73e8eSMarian Balakowicz case IH_OS_VXWORKS: name = "VxWorks"; break; 24242b73e8eSMarian Balakowicz case IH_OS_QNX: name = "QNX"; break; 24342b73e8eSMarian Balakowicz case IH_OS_U_BOOT: name = "U-Boot"; break; 24442b73e8eSMarian Balakowicz case IH_OS_RTEMS: name = "RTEMS"; break; 24542b73e8eSMarian Balakowicz #ifdef CONFIG_ARTOS 24642b73e8eSMarian Balakowicz case IH_OS_ARTOS: name = "ARTOS"; break; 24742b73e8eSMarian Balakowicz #endif 24842b73e8eSMarian Balakowicz #ifdef CONFIG_LYNXKDI 24942b73e8eSMarian Balakowicz case IH_OS_LYNXOS: name = "LynxOS"; break; 25042b73e8eSMarian Balakowicz #endif 25142b73e8eSMarian Balakowicz default: name = "Unknown OS"; break; 25242b73e8eSMarian Balakowicz } 25342b73e8eSMarian Balakowicz 25442b73e8eSMarian Balakowicz return name; 25542b73e8eSMarian Balakowicz } 25642b73e8eSMarian Balakowicz 25742b73e8eSMarian Balakowicz const char* image_get_arch_name (uint8_t arch) 25842b73e8eSMarian Balakowicz { 25942b73e8eSMarian Balakowicz const char *name; 26042b73e8eSMarian Balakowicz 26142b73e8eSMarian Balakowicz switch (arch) { 26242b73e8eSMarian Balakowicz case IH_ARCH_INVALID: name = "Invalid Architecture"; break; 26342b73e8eSMarian Balakowicz case IH_ARCH_ALPHA: name = "Alpha"; break; 26442b73e8eSMarian Balakowicz case IH_ARCH_ARM: name = "ARM"; break; 26542b73e8eSMarian Balakowicz case IH_ARCH_AVR32: name = "AVR32"; break; 26642b73e8eSMarian Balakowicz case IH_ARCH_BLACKFIN: name = "Blackfin"; break; 26742b73e8eSMarian Balakowicz case IH_ARCH_I386: name = "Intel x86"; break; 26842b73e8eSMarian Balakowicz case IH_ARCH_IA64: name = "IA64"; break; 26942b73e8eSMarian Balakowicz case IH_ARCH_M68K: name = "M68K"; break; 27042b73e8eSMarian Balakowicz case IH_ARCH_MICROBLAZE:name = "Microblaze"; break; 27142b73e8eSMarian Balakowicz case IH_ARCH_MIPS64: name = "MIPS 64 Bit"; break; 27242b73e8eSMarian Balakowicz case IH_ARCH_MIPS: name = "MIPS"; break; 27342b73e8eSMarian Balakowicz case IH_ARCH_NIOS2: name = "Nios-II"; break; 27442b73e8eSMarian Balakowicz case IH_ARCH_NIOS: name = "Nios"; break; 27542b73e8eSMarian Balakowicz case IH_ARCH_PPC: name = "PowerPC"; break; 27642b73e8eSMarian Balakowicz case IH_ARCH_S390: name = "IBM S390"; break; 27742b73e8eSMarian Balakowicz case IH_ARCH_SH: name = "SuperH"; break; 27842b73e8eSMarian Balakowicz case IH_ARCH_SPARC64: name = "SPARC 64 Bit"; break; 27942b73e8eSMarian Balakowicz case IH_ARCH_SPARC: name = "SPARC"; break; 28042b73e8eSMarian Balakowicz default: name = "Unknown Architecture"; break; 28142b73e8eSMarian Balakowicz } 28242b73e8eSMarian Balakowicz 28342b73e8eSMarian Balakowicz return name; 28442b73e8eSMarian Balakowicz } 28542b73e8eSMarian Balakowicz 28642b73e8eSMarian Balakowicz const char* image_get_type_name (uint8_t type) 28742b73e8eSMarian Balakowicz { 28842b73e8eSMarian Balakowicz const char *name; 28942b73e8eSMarian Balakowicz 29042b73e8eSMarian Balakowicz switch (type) { 29142b73e8eSMarian Balakowicz case IH_TYPE_INVALID: name = "Invalid Image"; break; 29242b73e8eSMarian Balakowicz case IH_TYPE_STANDALONE:name = "Standalone Program"; break; 29342b73e8eSMarian Balakowicz case IH_TYPE_KERNEL: name = "Kernel Image"; break; 29442b73e8eSMarian Balakowicz case IH_TYPE_RAMDISK: name = "RAMDisk Image"; break; 29542b73e8eSMarian Balakowicz case IH_TYPE_MULTI: name = "Multi-File Image"; break; 29642b73e8eSMarian Balakowicz case IH_TYPE_FIRMWARE: name = "Firmware"; break; 29742b73e8eSMarian Balakowicz case IH_TYPE_SCRIPT: name = "Script"; break; 29842b73e8eSMarian Balakowicz case IH_TYPE_FLATDT: name = "Flat Device Tree"; break; 29942b73e8eSMarian Balakowicz default: name = "Unknown Image"; break; 30042b73e8eSMarian Balakowicz } 30142b73e8eSMarian Balakowicz 30242b73e8eSMarian Balakowicz return name; 30342b73e8eSMarian Balakowicz } 30442b73e8eSMarian Balakowicz 30542b73e8eSMarian Balakowicz const char* image_get_comp_name (uint8_t comp) 30642b73e8eSMarian Balakowicz { 30742b73e8eSMarian Balakowicz const char *name; 30842b73e8eSMarian Balakowicz 30942b73e8eSMarian Balakowicz switch (comp) { 31042b73e8eSMarian Balakowicz case IH_COMP_NONE: name = "uncompressed"; break; 31142b73e8eSMarian Balakowicz case IH_COMP_GZIP: name = "gzip compressed"; break; 31242b73e8eSMarian Balakowicz case IH_COMP_BZIP2: name = "bzip2 compressed"; break; 31342b73e8eSMarian Balakowicz default: name = "unknown compression"; break; 31442b73e8eSMarian Balakowicz } 31542b73e8eSMarian Balakowicz 31642b73e8eSMarian Balakowicz return name; 31742b73e8eSMarian Balakowicz } 3185ad03eb3SMarian Balakowicz 3192242f536SMarian Balakowicz static void image_print_type (image_header_t *hdr) 3202242f536SMarian Balakowicz { 3212242f536SMarian Balakowicz const char *os, *arch, *type, *comp; 3222242f536SMarian Balakowicz 3232242f536SMarian Balakowicz os = image_get_os_name (image_get_os (hdr)); 3242242f536SMarian Balakowicz arch = image_get_arch_name (image_get_arch (hdr)); 3252242f536SMarian Balakowicz type = image_get_type_name (image_get_type (hdr)); 3262242f536SMarian Balakowicz comp = image_get_comp_name (image_get_comp (hdr)); 3272242f536SMarian Balakowicz 3282242f536SMarian Balakowicz printf ("%s %s %s (%s)", arch, os, type, comp); 3292242f536SMarian Balakowicz } 3302242f536SMarian Balakowicz 3312242f536SMarian Balakowicz void image_print_contents (image_header_t *hdr) 3322242f536SMarian Balakowicz { 3332242f536SMarian Balakowicz #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) 3342242f536SMarian Balakowicz time_t timestamp = (time_t)image_get_time (hdr); 3352242f536SMarian Balakowicz struct rtc_time tm; 3362242f536SMarian Balakowicz #endif 3372242f536SMarian Balakowicz 3382242f536SMarian Balakowicz printf (" Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); 3392242f536SMarian Balakowicz 3402242f536SMarian Balakowicz #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) 3412242f536SMarian Balakowicz to_tm (timestamp, &tm); 3422242f536SMarian Balakowicz printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", 3432242f536SMarian Balakowicz tm.tm_year, tm.tm_mon, tm.tm_mday, 3442242f536SMarian Balakowicz tm.tm_hour, tm.tm_min, tm.tm_sec); 3452242f536SMarian Balakowicz #endif 3462242f536SMarian Balakowicz puts (" Image Type: "); 3472242f536SMarian Balakowicz image_print_type (hdr); 3482242f536SMarian Balakowicz 3492242f536SMarian Balakowicz printf ("\n Data Size: %d Bytes = ", image_get_data_size (hdr)); 3502242f536SMarian Balakowicz print_size (image_get_data_size (hdr), "\n"); 3512242f536SMarian Balakowicz printf (" Load Address: %08x\n" 3522242f536SMarian Balakowicz " Entry Point: %08x\n", 3532242f536SMarian Balakowicz image_get_load (hdr), image_get_ep (hdr)); 3542242f536SMarian Balakowicz 3552242f536SMarian Balakowicz if (image_check_type (hdr, IH_TYPE_MULTI)) { 3562242f536SMarian Balakowicz int i; 3572242f536SMarian Balakowicz ulong data, len; 3582242f536SMarian Balakowicz ulong count = image_multi_count (hdr); 3592242f536SMarian Balakowicz 3602242f536SMarian Balakowicz puts (" Contents:\n"); 3612242f536SMarian Balakowicz for (i = 0; i < count; i++) { 3622242f536SMarian Balakowicz image_multi_getimg (hdr, i, &data, &len); 3632242f536SMarian Balakowicz printf (" Image %d: %8ld Bytes = ", i, len); 3642242f536SMarian Balakowicz print_size (len, "\n"); 3652242f536SMarian Balakowicz } 3662242f536SMarian Balakowicz } 3672242f536SMarian Balakowicz } 3682242f536SMarian Balakowicz 3695ad03eb3SMarian Balakowicz /** 370fff888a1SMarian Balakowicz * gen_image_get_format - get image format type 371fff888a1SMarian Balakowicz * @img_addr: image start address 372fff888a1SMarian Balakowicz * 373fff888a1SMarian Balakowicz * gen_image_get_format() checks whether provided address points to a valid 374fff888a1SMarian Balakowicz * legacy or FIT image. 375fff888a1SMarian Balakowicz * 3764efbe9dbSMarian Balakowicz * New uImage format and FDT blob are based on a libfdt. FDT blob 3774efbe9dbSMarian Balakowicz * may be passed directly or embedded in a FIT image. In both situations 3784efbe9dbSMarian Balakowicz * gen_image_get_format() must be able to dectect libfdt header. 3794efbe9dbSMarian Balakowicz * 380fff888a1SMarian Balakowicz * returns: 381fff888a1SMarian Balakowicz * image format type or IMAGE_FORMAT_INVALID if no image is present 382fff888a1SMarian Balakowicz */ 383fff888a1SMarian Balakowicz int gen_image_get_format (void *img_addr) 384fff888a1SMarian Balakowicz { 385fff888a1SMarian Balakowicz ulong format = IMAGE_FORMAT_INVALID; 386fff888a1SMarian Balakowicz image_header_t *hdr; 3874efbe9dbSMarian Balakowicz #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) 388fff888a1SMarian Balakowicz char *fit_hdr; 389fff888a1SMarian Balakowicz #endif 390fff888a1SMarian Balakowicz 391fff888a1SMarian Balakowicz hdr = (image_header_t *)img_addr; 392fff888a1SMarian Balakowicz if (image_check_magic(hdr)) 393fff888a1SMarian Balakowicz format = IMAGE_FORMAT_LEGACY; 3944efbe9dbSMarian Balakowicz #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) 395fff888a1SMarian Balakowicz else { 396fff888a1SMarian Balakowicz fit_hdr = (char *)img_addr; 397fff888a1SMarian Balakowicz if (fdt_check_header (fit_hdr) == 0) 398fff888a1SMarian Balakowicz format = IMAGE_FORMAT_FIT; 399fff888a1SMarian Balakowicz } 400fff888a1SMarian Balakowicz #endif 401fff888a1SMarian Balakowicz 402fff888a1SMarian Balakowicz return format; 403fff888a1SMarian Balakowicz } 404fff888a1SMarian Balakowicz 405fff888a1SMarian Balakowicz /** 406fff888a1SMarian Balakowicz * gen_get_image - get image from special storage (if necessary) 407fff888a1SMarian Balakowicz * @img_addr: image start address 408fff888a1SMarian Balakowicz * 409fff888a1SMarian Balakowicz * gen_get_image() checks if provided image start adddress is located 410fff888a1SMarian Balakowicz * in a dataflash storage. If so, image is moved to a system RAM memory. 411fff888a1SMarian Balakowicz * 412fff888a1SMarian Balakowicz * returns: 413fff888a1SMarian Balakowicz * image start address after possible relocation from special storage 414fff888a1SMarian Balakowicz */ 415fff888a1SMarian Balakowicz ulong gen_get_image (ulong img_addr) 416fff888a1SMarian Balakowicz { 4176f0f9dfcSMarian Balakowicz ulong ram_addr = img_addr; 418fff888a1SMarian Balakowicz 4196f0f9dfcSMarian Balakowicz #ifdef CONFIG_HAS_DATAFLASH 4206f0f9dfcSMarian Balakowicz ulong h_size, d_size; 4216f0f9dfcSMarian Balakowicz 4226f0f9dfcSMarian Balakowicz if (addr_dataflash (img_addr)){ 4236f0f9dfcSMarian Balakowicz /* ger RAM address */ 4246f0f9dfcSMarian Balakowicz ram_addr = CFG_LOAD_ADDR; 4256f0f9dfcSMarian Balakowicz 4266f0f9dfcSMarian Balakowicz /* get header size */ 427fff888a1SMarian Balakowicz h_size = image_get_header_size (); 428fff888a1SMarian Balakowicz #if defined(CONFIG_FIT) 429fff888a1SMarian Balakowicz if (sizeof(struct fdt_header) > h_size) 430fff888a1SMarian Balakowicz h_size = sizeof(struct fdt_header); 431fff888a1SMarian Balakowicz #endif 432fff888a1SMarian Balakowicz 4336f0f9dfcSMarian Balakowicz /* read in header */ 434fff888a1SMarian Balakowicz debug (" Reading image header from dataflash address " 435fff888a1SMarian Balakowicz "%08lx to RAM address %08lx\n", img_addr, ram_addr); 4366f0f9dfcSMarian Balakowicz 437fff888a1SMarian Balakowicz read_dataflash (img_addr, h_size, (char *)ram_addr); 438fff888a1SMarian Balakowicz 4396f0f9dfcSMarian Balakowicz /* get data size */ 440fff888a1SMarian Balakowicz switch (gen_image_get_format ((void *)ram_addr)) { 441fff888a1SMarian Balakowicz case IMAGE_FORMAT_LEGACY: 442fff888a1SMarian Balakowicz d_size = image_get_data_size ((image_header_t *)ram_addr); 443fff888a1SMarian Balakowicz debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n", 444fff888a1SMarian Balakowicz ram_addr, d_size); 445fff888a1SMarian Balakowicz break; 446fff888a1SMarian Balakowicz #if defined(CONFIG_FIT) 447fff888a1SMarian Balakowicz case IMAGE_FORMAT_FIT: 448fff888a1SMarian Balakowicz d_size = fdt_totalsize((void *)ram_addr) - h_size; 449fff888a1SMarian Balakowicz debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n", 450fff888a1SMarian Balakowicz ram_addr, d_size); 451fff888a1SMarian Balakowicz break; 452fff888a1SMarian Balakowicz #endif 453fff888a1SMarian Balakowicz default: 454fff888a1SMarian Balakowicz printf (" No valid image found at 0x%08lx\n", img_addr); 455fff888a1SMarian Balakowicz return ram_addr; 456fff888a1SMarian Balakowicz } 457fff888a1SMarian Balakowicz 4586f0f9dfcSMarian Balakowicz /* read in image data */ 459fff888a1SMarian Balakowicz debug (" Reading image remaining data from dataflash address " 460fff888a1SMarian Balakowicz "%08lx to RAM address %08lx\n", img_addr + h_size, 461fff888a1SMarian Balakowicz ram_addr + h_size); 462fff888a1SMarian Balakowicz 463fff888a1SMarian Balakowicz read_dataflash (img_addr + h_size, d_size, 464fff888a1SMarian Balakowicz (char *)(ram_addr + h_size)); 4656f0f9dfcSMarian Balakowicz 466fff888a1SMarian Balakowicz } 4676f0f9dfcSMarian Balakowicz #endif /* CONFIG_HAS_DATAFLASH */ 468fff888a1SMarian Balakowicz 469fff888a1SMarian Balakowicz return ram_addr; 470fff888a1SMarian Balakowicz } 471fff888a1SMarian Balakowicz 472fff888a1SMarian Balakowicz /** 4735ad03eb3SMarian Balakowicz * image_get_ramdisk - get and verify ramdisk image 4745ad03eb3SMarian Balakowicz * @cmdtp: command table pointer 4755ad03eb3SMarian Balakowicz * @flag: command flag 4765ad03eb3SMarian Balakowicz * @argc: command argument count 4775ad03eb3SMarian Balakowicz * @argv: command argument list 4785ad03eb3SMarian Balakowicz * @rd_addr: ramdisk image start address 4795ad03eb3SMarian Balakowicz * @arch: expected ramdisk architecture 4805ad03eb3SMarian Balakowicz * @verify: checksum verification flag 4815ad03eb3SMarian Balakowicz * 4825ad03eb3SMarian Balakowicz * image_get_ramdisk() returns a pointer to the verified ramdisk image 4835ad03eb3SMarian Balakowicz * header. Routine receives image start address and expected architecture 4845ad03eb3SMarian Balakowicz * flag. Verification done covers data and header integrity and os/type/arch 4855ad03eb3SMarian Balakowicz * fields checking. 4865ad03eb3SMarian Balakowicz * 4875ad03eb3SMarian Balakowicz * If dataflash support is enabled routine checks for dataflash addresses 4885ad03eb3SMarian Balakowicz * and handles required dataflash reads. 4895ad03eb3SMarian Balakowicz * 4905ad03eb3SMarian Balakowicz * returns: 4915ad03eb3SMarian Balakowicz * pointer to a ramdisk image header, if image was found and valid 492*274cea2bSKumar Gala * otherwise, return NULL 4935ad03eb3SMarian Balakowicz */ 4948a5ea3e6SMarian Balakowicz static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, 4955ad03eb3SMarian Balakowicz int argc, char *argv[], 4965ad03eb3SMarian Balakowicz ulong rd_addr, uint8_t arch, int verify) 4975ad03eb3SMarian Balakowicz { 4985ad03eb3SMarian Balakowicz image_header_t *rd_hdr; 4995ad03eb3SMarian Balakowicz 5005ad03eb3SMarian Balakowicz show_boot_progress (9); 5015ad03eb3SMarian Balakowicz rd_hdr = (image_header_t *)rd_addr; 5025ad03eb3SMarian Balakowicz 5035ad03eb3SMarian Balakowicz if (!image_check_magic (rd_hdr)) { 5045ad03eb3SMarian Balakowicz puts ("Bad Magic Number\n"); 5055ad03eb3SMarian Balakowicz show_boot_progress (-10); 506*274cea2bSKumar Gala return NULL; 5075ad03eb3SMarian Balakowicz } 5085ad03eb3SMarian Balakowicz 5095ad03eb3SMarian Balakowicz if (!image_check_hcrc (rd_hdr)) { 5105ad03eb3SMarian Balakowicz puts ("Bad Header Checksum\n"); 5115ad03eb3SMarian Balakowicz show_boot_progress (-11); 512*274cea2bSKumar Gala return NULL; 5135ad03eb3SMarian Balakowicz } 5145ad03eb3SMarian Balakowicz 5155ad03eb3SMarian Balakowicz show_boot_progress (10); 5162242f536SMarian Balakowicz image_print_contents (rd_hdr); 5175ad03eb3SMarian Balakowicz 5185ad03eb3SMarian Balakowicz if (verify) { 5195ad03eb3SMarian Balakowicz puts(" Verifying Checksum ... "); 5205ad03eb3SMarian Balakowicz if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { 5215ad03eb3SMarian Balakowicz puts ("Bad Data CRC\n"); 5225ad03eb3SMarian Balakowicz show_boot_progress (-12); 523*274cea2bSKumar Gala return NULL; 5245ad03eb3SMarian Balakowicz } 5255ad03eb3SMarian Balakowicz puts("OK\n"); 5265ad03eb3SMarian Balakowicz } 5275ad03eb3SMarian Balakowicz 5285ad03eb3SMarian Balakowicz show_boot_progress (11); 5295ad03eb3SMarian Balakowicz 5305ad03eb3SMarian Balakowicz if (!image_check_os (rd_hdr, IH_OS_LINUX) || 5315ad03eb3SMarian Balakowicz !image_check_arch (rd_hdr, arch) || 5325ad03eb3SMarian Balakowicz !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { 5335ad03eb3SMarian Balakowicz printf ("No Linux %s Ramdisk Image\n", 5345ad03eb3SMarian Balakowicz image_get_arch_name(arch)); 5355ad03eb3SMarian Balakowicz show_boot_progress (-13); 536*274cea2bSKumar Gala return NULL; 5375ad03eb3SMarian Balakowicz } 5385ad03eb3SMarian Balakowicz 5395ad03eb3SMarian Balakowicz return rd_hdr; 5405ad03eb3SMarian Balakowicz } 5415ad03eb3SMarian Balakowicz 5425ad03eb3SMarian Balakowicz /** 5435ad03eb3SMarian Balakowicz * get_ramdisk - main ramdisk handling routine 5445ad03eb3SMarian Balakowicz * @cmdtp: command table pointer 5455ad03eb3SMarian Balakowicz * @flag: command flag 5465ad03eb3SMarian Balakowicz * @argc: command argument count 5475ad03eb3SMarian Balakowicz * @argv: command argument list 5488a5ea3e6SMarian Balakowicz * @images: pointer to the bootm images structure 5495ad03eb3SMarian Balakowicz * @arch: expected ramdisk architecture 5505ad03eb3SMarian Balakowicz * @rd_start: pointer to a ulong variable, will hold ramdisk start address 5515ad03eb3SMarian Balakowicz * @rd_end: pointer to a ulong variable, will hold ramdisk end 5525ad03eb3SMarian Balakowicz * 5535ad03eb3SMarian Balakowicz * get_ramdisk() is responsible for finding a valid ramdisk image. 5545ad03eb3SMarian Balakowicz * Curently supported are the following ramdisk sources: 5555ad03eb3SMarian Balakowicz * - multicomponent kernel/ramdisk image, 5565ad03eb3SMarian Balakowicz * - commandline provided address of decicated ramdisk image. 5575ad03eb3SMarian Balakowicz * 5585ad03eb3SMarian Balakowicz * returns: 5595ad03eb3SMarian Balakowicz * rd_start and rd_end are set to ramdisk start/end addresses if 5605ad03eb3SMarian Balakowicz * ramdisk image is found and valid 5615ad03eb3SMarian Balakowicz * rd_start and rd_end are set to 0 if no ramdisk exists 562*274cea2bSKumar Gala * return 1 if ramdisk image is found but corrupted 5635ad03eb3SMarian Balakowicz */ 564*274cea2bSKumar Gala int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], 5658a5ea3e6SMarian Balakowicz bootm_headers_t *images, uint8_t arch, 5665ad03eb3SMarian Balakowicz ulong *rd_start, ulong *rd_end) 5675ad03eb3SMarian Balakowicz { 568d5934ad7SMarian Balakowicz ulong rd_addr, rd_load; 5695ad03eb3SMarian Balakowicz ulong rd_data, rd_len; 5705ad03eb3SMarian Balakowicz image_header_t *rd_hdr; 571d5934ad7SMarian Balakowicz #if defined(CONFIG_FIT) 572d5934ad7SMarian Balakowicz void *fit_hdr; 573d5934ad7SMarian Balakowicz const char *fit_uname_config = NULL; 574d5934ad7SMarian Balakowicz const char *fit_uname_ramdisk = NULL; 575d5934ad7SMarian Balakowicz ulong default_addr; 576d5934ad7SMarian Balakowicz #endif 5775ad03eb3SMarian Balakowicz 5785ad03eb3SMarian Balakowicz /* 5795ad03eb3SMarian Balakowicz * Look for a '-' which indicates to ignore the 5805ad03eb3SMarian Balakowicz * ramdisk argument 5815ad03eb3SMarian Balakowicz */ 582d5934ad7SMarian Balakowicz if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) { 5835ad03eb3SMarian Balakowicz debug ("## Skipping init Ramdisk\n"); 5845ad03eb3SMarian Balakowicz rd_len = rd_data = 0; 585d5934ad7SMarian Balakowicz } else if (argc >= 3) { 586d5934ad7SMarian Balakowicz #if defined(CONFIG_FIT) 587d5934ad7SMarian Balakowicz /* 588d5934ad7SMarian Balakowicz * If the init ramdisk comes from the FIT image and the FIT image 589d5934ad7SMarian Balakowicz * address is omitted in the command line argument, try to use 590d5934ad7SMarian Balakowicz * os FIT image address or default load address. 591d5934ad7SMarian Balakowicz */ 592d5934ad7SMarian Balakowicz if (images->fit_uname_os) 593d5934ad7SMarian Balakowicz default_addr = (ulong)images->fit_hdr_os; 594d5934ad7SMarian Balakowicz else 595d5934ad7SMarian Balakowicz default_addr = load_addr; 596d5934ad7SMarian Balakowicz 597d5934ad7SMarian Balakowicz if (fit_parse_conf (argv[2], default_addr, 598d5934ad7SMarian Balakowicz &rd_addr, &fit_uname_config)) { 599d5934ad7SMarian Balakowicz debug ("* ramdisk: config '%s' from image at 0x%08lx\n", 600d5934ad7SMarian Balakowicz fit_uname_config, rd_addr); 601d5934ad7SMarian Balakowicz } else if (fit_parse_subimage (argv[2], default_addr, 602d5934ad7SMarian Balakowicz &rd_addr, &fit_uname_ramdisk)) { 603d5934ad7SMarian Balakowicz debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n", 604d5934ad7SMarian Balakowicz fit_uname_ramdisk, rd_addr); 605d5934ad7SMarian Balakowicz } else 606d5934ad7SMarian Balakowicz #endif 607d5934ad7SMarian Balakowicz { 608d5934ad7SMarian Balakowicz rd_addr = simple_strtoul(argv[2], NULL, 16); 609d5934ad7SMarian Balakowicz debug ("* ramdisk: cmdline image address = 0x%08lx\n", 610d5934ad7SMarian Balakowicz rd_addr); 611d5934ad7SMarian Balakowicz } 612d5934ad7SMarian Balakowicz 613d5934ad7SMarian Balakowicz /* copy from dataflash if needed */ 614d5934ad7SMarian Balakowicz printf ("## Loading init Ramdisk Image at %08lx ...\n", 615d5934ad7SMarian Balakowicz rd_addr); 616d5934ad7SMarian Balakowicz rd_addr = gen_get_image (rd_addr); 617d5934ad7SMarian Balakowicz 6185ad03eb3SMarian Balakowicz /* 6195ad03eb3SMarian Balakowicz * Check if there is an initrd image at the 6205ad03eb3SMarian Balakowicz * address provided in the second bootm argument 621d5934ad7SMarian Balakowicz * check image type, for FIT images get FIT node. 6225ad03eb3SMarian Balakowicz */ 623d5934ad7SMarian Balakowicz switch (gen_image_get_format ((void *)rd_addr)) { 624d5934ad7SMarian Balakowicz case IMAGE_FORMAT_LEGACY: 625d5934ad7SMarian Balakowicz 626d5934ad7SMarian Balakowicz debug ("* ramdisk: legacy format image\n"); 6275ad03eb3SMarian Balakowicz 6285ad03eb3SMarian Balakowicz rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, 6298a5ea3e6SMarian Balakowicz rd_addr, arch, images->verify); 6305ad03eb3SMarian Balakowicz 631*274cea2bSKumar Gala if (rd_hdr == NULL) { 632*274cea2bSKumar Gala *rd_start = 0; 633*274cea2bSKumar Gala *rd_end = 0; 634*274cea2bSKumar Gala return 1; 635*274cea2bSKumar Gala } 636*274cea2bSKumar Gala 6375ad03eb3SMarian Balakowicz rd_data = image_get_data (rd_hdr); 6385ad03eb3SMarian Balakowicz rd_len = image_get_data_size (rd_hdr); 639d5934ad7SMarian Balakowicz rd_load = image_get_load (rd_hdr); 640d5934ad7SMarian Balakowicz break; 641d5934ad7SMarian Balakowicz #if defined(CONFIG_FIT) 642d5934ad7SMarian Balakowicz case IMAGE_FORMAT_FIT: 643d5934ad7SMarian Balakowicz fit_hdr = (void *)rd_addr; 644d5934ad7SMarian Balakowicz debug ("* ramdisk: FIT format image\n"); 645d5934ad7SMarian Balakowicz fit_unsupported_reset ("ramdisk"); 646*274cea2bSKumar Gala return 1; 647d5934ad7SMarian Balakowicz #endif 648d5934ad7SMarian Balakowicz default: 649d5934ad7SMarian Balakowicz printf ("Wrong Image Format for %s command\n", 650d5934ad7SMarian Balakowicz cmdtp->name); 651d5934ad7SMarian Balakowicz rd_data = rd_len = 0; 652d5934ad7SMarian Balakowicz } 6535ad03eb3SMarian Balakowicz 6545ad03eb3SMarian Balakowicz #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) 6555ad03eb3SMarian Balakowicz /* 656d5934ad7SMarian Balakowicz * We need to copy the ramdisk to SRAM to let Linux boot 6575ad03eb3SMarian Balakowicz */ 658d5934ad7SMarian Balakowicz if (rd_data) { 659d5934ad7SMarian Balakowicz memmove ((void *)rd_load, (uchar *)rd_data, rd_len); 660d5934ad7SMarian Balakowicz rd_data = rd_load; 6615ad03eb3SMarian Balakowicz } 662d5934ad7SMarian Balakowicz #endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */ 6635ad03eb3SMarian Balakowicz 664d5934ad7SMarian Balakowicz } else if (images->legacy_hdr_valid && 665d5934ad7SMarian Balakowicz image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) { 6665ad03eb3SMarian Balakowicz /* 667d5934ad7SMarian Balakowicz * Now check if we have a legacy mult-component image, 668d5934ad7SMarian Balakowicz * get second entry data start address and len. 6695ad03eb3SMarian Balakowicz */ 6705ad03eb3SMarian Balakowicz show_boot_progress (13); 6715ad03eb3SMarian Balakowicz printf ("## Loading init Ramdisk from multi component " 672d5934ad7SMarian Balakowicz "Image at %08lx ...\n", 673d5934ad7SMarian Balakowicz (ulong)images->legacy_hdr_os); 674d5934ad7SMarian Balakowicz 675d5934ad7SMarian Balakowicz image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len); 6765ad03eb3SMarian Balakowicz } else { 6775ad03eb3SMarian Balakowicz /* 6785ad03eb3SMarian Balakowicz * no initrd image 6795ad03eb3SMarian Balakowicz */ 6805ad03eb3SMarian Balakowicz show_boot_progress (14); 6815ad03eb3SMarian Balakowicz rd_len = rd_data = 0; 6825ad03eb3SMarian Balakowicz } 6835ad03eb3SMarian Balakowicz 6845ad03eb3SMarian Balakowicz if (!rd_data) { 6855ad03eb3SMarian Balakowicz debug ("## No init Ramdisk\n"); 6865ad03eb3SMarian Balakowicz *rd_start = 0; 6875ad03eb3SMarian Balakowicz *rd_end = 0; 6885ad03eb3SMarian Balakowicz } else { 6895ad03eb3SMarian Balakowicz *rd_start = rd_data; 6905ad03eb3SMarian Balakowicz *rd_end = rd_data + rd_len; 6915ad03eb3SMarian Balakowicz } 6925ad03eb3SMarian Balakowicz debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", 6935ad03eb3SMarian Balakowicz *rd_start, *rd_end); 694*274cea2bSKumar Gala 695*274cea2bSKumar Gala return 0; 6965ad03eb3SMarian Balakowicz } 697ceaed2b1SMarian Balakowicz 698ceaed2b1SMarian Balakowicz #if defined(CONFIG_PPC) || defined(CONFIG_M68K) 699ceaed2b1SMarian Balakowicz /** 700ceaed2b1SMarian Balakowicz * ramdisk_high - relocate init ramdisk 701ceaed2b1SMarian Balakowicz * @rd_data: ramdisk data start address 702ceaed2b1SMarian Balakowicz * @rd_len: ramdisk data length 703ceaed2b1SMarian Balakowicz * @sp_limit: stack pointer limit (including BOOTMAPSZ) 704ceaed2b1SMarian Balakowicz * @sp: current stack pointer 705ceaed2b1SMarian Balakowicz * @initrd_start: pointer to a ulong variable, will hold final init ramdisk 706ceaed2b1SMarian Balakowicz * start address (after possible relocation) 707ceaed2b1SMarian Balakowicz * @initrd_end: pointer to a ulong variable, will hold final init ramdisk 708ceaed2b1SMarian Balakowicz * end address (after possible relocation) 709ceaed2b1SMarian Balakowicz * 710ceaed2b1SMarian Balakowicz * ramdisk_high() takes a relocation hint from "initrd_high" environement 711ceaed2b1SMarian Balakowicz * variable and if requested ramdisk data is moved to a specified location. 712ceaed2b1SMarian Balakowicz * 713ceaed2b1SMarian Balakowicz * returns: 714b6b0fe64SMarian Balakowicz * - initrd_start and initrd_end are set to final (after relocation) ramdisk 715ceaed2b1SMarian Balakowicz * start/end addresses if ramdisk image start and len were provided 716b6b0fe64SMarian Balakowicz * otherwise set initrd_start and initrd_end set to zeros 717b6b0fe64SMarian Balakowicz * - returns new allc_current, next free address below BOOTMAPSZ 718ceaed2b1SMarian Balakowicz */ 719b6b0fe64SMarian Balakowicz ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, 720a6612bdfSKumar Gala ulong sp_limit, ulong sp, 721b6b0fe64SMarian Balakowicz ulong *initrd_start, ulong *initrd_end) 722ceaed2b1SMarian Balakowicz { 723ceaed2b1SMarian Balakowicz char *s; 724ceaed2b1SMarian Balakowicz ulong initrd_high; 725ceaed2b1SMarian Balakowicz int initrd_copy_to_ram = 1; 726b6b0fe64SMarian Balakowicz ulong new_alloc_current = alloc_current; 727ceaed2b1SMarian Balakowicz 728ceaed2b1SMarian Balakowicz if ((s = getenv ("initrd_high")) != NULL) { 729ceaed2b1SMarian Balakowicz /* a value of "no" or a similar string will act like 0, 730ceaed2b1SMarian Balakowicz * turning the "load high" feature off. This is intentional. 731ceaed2b1SMarian Balakowicz */ 732ceaed2b1SMarian Balakowicz initrd_high = simple_strtoul (s, NULL, 16); 733ceaed2b1SMarian Balakowicz if (initrd_high == ~0) 734ceaed2b1SMarian Balakowicz initrd_copy_to_ram = 0; 735ceaed2b1SMarian Balakowicz } else { 736ceaed2b1SMarian Balakowicz /* not set, no restrictions to load high */ 737ceaed2b1SMarian Balakowicz initrd_high = ~0; 738ceaed2b1SMarian Balakowicz } 739ceaed2b1SMarian Balakowicz 740ceaed2b1SMarian Balakowicz #ifdef CONFIG_LOGBUFFER 741ceaed2b1SMarian Balakowicz /* Prevent initrd from overwriting logbuffer */ 742a6612bdfSKumar Gala if (initrd_high < (gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) 743a6612bdfSKumar Gala initrd_high = gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; 744a6612bdfSKumar Gala debug ("## Logbuffer at 0x%08lx ", gd->bd->bi_memsize - LOGBUFF_LEN); 745ceaed2b1SMarian Balakowicz #endif 746ceaed2b1SMarian Balakowicz debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", 747ceaed2b1SMarian Balakowicz initrd_high, initrd_copy_to_ram); 748ceaed2b1SMarian Balakowicz 749ceaed2b1SMarian Balakowicz if (rd_data) { 750ceaed2b1SMarian Balakowicz if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ 751ceaed2b1SMarian Balakowicz debug (" in-place initrd\n"); 752ceaed2b1SMarian Balakowicz *initrd_start = rd_data; 753ceaed2b1SMarian Balakowicz *initrd_end = rd_data + rd_len; 754ceaed2b1SMarian Balakowicz } else { 755b6b0fe64SMarian Balakowicz new_alloc_current = alloc_current - rd_len; 756b6b0fe64SMarian Balakowicz *initrd_start = new_alloc_current; 757ceaed2b1SMarian Balakowicz *initrd_start &= ~(4096 - 1); /* align on page */ 758ceaed2b1SMarian Balakowicz 759ceaed2b1SMarian Balakowicz if (initrd_high) { 760ceaed2b1SMarian Balakowicz ulong nsp; 761ceaed2b1SMarian Balakowicz 762ceaed2b1SMarian Balakowicz /* 763ceaed2b1SMarian Balakowicz * the inital ramdisk does not need to be within 764ceaed2b1SMarian Balakowicz * CFG_BOOTMAPSZ as it is not accessed until after 765ceaed2b1SMarian Balakowicz * the mm system is initialised. 766ceaed2b1SMarian Balakowicz * 767ceaed2b1SMarian Balakowicz * do the stack bottom calculation again and see if 768ceaed2b1SMarian Balakowicz * the initrd will fit just below the monitor stack 769ceaed2b1SMarian Balakowicz * bottom without overwriting the area allocated 770ceaed2b1SMarian Balakowicz * for command line args and board info. 771ceaed2b1SMarian Balakowicz */ 772ceaed2b1SMarian Balakowicz nsp = sp; 773ceaed2b1SMarian Balakowicz nsp -= 2048; /* just to be sure */ 774ceaed2b1SMarian Balakowicz nsp &= ~0xF; 775ceaed2b1SMarian Balakowicz 776ceaed2b1SMarian Balakowicz if (nsp > initrd_high) /* limit as specified */ 777ceaed2b1SMarian Balakowicz nsp = initrd_high; 778ceaed2b1SMarian Balakowicz 779ceaed2b1SMarian Balakowicz nsp -= rd_len; 780ceaed2b1SMarian Balakowicz nsp &= ~(4096 - 1); /* align on page */ 781ceaed2b1SMarian Balakowicz 782b6b0fe64SMarian Balakowicz if (nsp >= sp_limit) { 783ceaed2b1SMarian Balakowicz *initrd_start = nsp; 784b6b0fe64SMarian Balakowicz new_alloc_current = alloc_current; 785b6b0fe64SMarian Balakowicz } 786ceaed2b1SMarian Balakowicz } 787ceaed2b1SMarian Balakowicz 788ceaed2b1SMarian Balakowicz show_boot_progress (12); 789ceaed2b1SMarian Balakowicz 790ceaed2b1SMarian Balakowicz *initrd_end = *initrd_start + rd_len; 791ceaed2b1SMarian Balakowicz printf (" Loading Ramdisk to %08lx, end %08lx ... ", 792ceaed2b1SMarian Balakowicz *initrd_start, *initrd_end); 793ceaed2b1SMarian Balakowicz 794ceaed2b1SMarian Balakowicz memmove_wd((void *)*initrd_start, 795ceaed2b1SMarian Balakowicz (void *)rd_data, rd_len, CHUNKSZ); 796ceaed2b1SMarian Balakowicz 797ceaed2b1SMarian Balakowicz puts ("OK\n"); 798ceaed2b1SMarian Balakowicz } 799ceaed2b1SMarian Balakowicz } else { 800ceaed2b1SMarian Balakowicz *initrd_start = 0; 801ceaed2b1SMarian Balakowicz *initrd_end = 0; 802ceaed2b1SMarian Balakowicz } 803ceaed2b1SMarian Balakowicz debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", 804ceaed2b1SMarian Balakowicz *initrd_start, *initrd_end); 805b6b0fe64SMarian Balakowicz 806b6b0fe64SMarian Balakowicz return new_alloc_current; 807b6b0fe64SMarian Balakowicz } 808b6b0fe64SMarian Balakowicz 809b6b0fe64SMarian Balakowicz /** 810b6b0fe64SMarian Balakowicz * get_boot_sp_limit - calculate stack pointer limit 811b6b0fe64SMarian Balakowicz * @sp: current stack pointer 812b6b0fe64SMarian Balakowicz * 813b6b0fe64SMarian Balakowicz * get_boot_sp_limit() takes current stack pointer adrress and calculates 814b6b0fe64SMarian Balakowicz * stack pointer limit, below which kernel boot data (cmdline, board info, 815b6b0fe64SMarian Balakowicz * etc.) will be allocated. 816b6b0fe64SMarian Balakowicz * 817b6b0fe64SMarian Balakowicz * returns: 818b6b0fe64SMarian Balakowicz * stack pointer limit 819b6b0fe64SMarian Balakowicz */ 820b6b0fe64SMarian Balakowicz ulong get_boot_sp_limit(ulong sp) 821b6b0fe64SMarian Balakowicz { 822b6b0fe64SMarian Balakowicz ulong sp_limit = sp; 823b6b0fe64SMarian Balakowicz 824b6b0fe64SMarian Balakowicz sp_limit -= 2048; /* just to be sure */ 825b6b0fe64SMarian Balakowicz 826b6b0fe64SMarian Balakowicz /* make sure sp_limit is within kernel mapped space */ 827b6b0fe64SMarian Balakowicz if (sp_limit > CFG_BOOTMAPSZ) 828b6b0fe64SMarian Balakowicz sp_limit = CFG_BOOTMAPSZ; 829b6b0fe64SMarian Balakowicz sp_limit &= ~0xF; 830b6b0fe64SMarian Balakowicz 831b6b0fe64SMarian Balakowicz return sp_limit; 832b6b0fe64SMarian Balakowicz } 833b6b0fe64SMarian Balakowicz 834b6b0fe64SMarian Balakowicz /** 835b6b0fe64SMarian Balakowicz * get_boot_cmdline - allocate and initialize kernel cmdline 836b6b0fe64SMarian Balakowicz * @alloc_current: current boot allocation address (counting down 837b6b0fe64SMarian Balakowicz * from sp_limit) 838b6b0fe64SMarian Balakowicz * @cmd_start: pointer to a ulong variable, will hold cmdline start 839b6b0fe64SMarian Balakowicz * @cmd_end: pointer to a ulong variable, will hold cmdline end 840b6b0fe64SMarian Balakowicz * 841b6b0fe64SMarian Balakowicz * get_boot_cmdline() allocates space for kernel command line below 842b6b0fe64SMarian Balakowicz * provided alloc_current address. If "bootargs" U-boot environemnt 843b6b0fe64SMarian Balakowicz * variable is present its contents is copied to allocated kernel 844b6b0fe64SMarian Balakowicz * command line. 845b6b0fe64SMarian Balakowicz * 846b6b0fe64SMarian Balakowicz * returns: 847b6b0fe64SMarian Balakowicz * alloc_current after cmdline allocation 848b6b0fe64SMarian Balakowicz */ 849b6b0fe64SMarian Balakowicz ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end) 850b6b0fe64SMarian Balakowicz { 851b6b0fe64SMarian Balakowicz char *cmdline; 852b6b0fe64SMarian Balakowicz char *s; 853b6b0fe64SMarian Balakowicz 854b6b0fe64SMarian Balakowicz cmdline = (char *)((alloc_current - CFG_BARGSIZE) & ~0xF); 855b6b0fe64SMarian Balakowicz 856b6b0fe64SMarian Balakowicz if ((s = getenv("bootargs")) == NULL) 857b6b0fe64SMarian Balakowicz s = ""; 858b6b0fe64SMarian Balakowicz 859b6b0fe64SMarian Balakowicz strcpy(cmdline, s); 860b6b0fe64SMarian Balakowicz 861b6b0fe64SMarian Balakowicz *cmd_start = (ulong) & cmdline[0]; 862b6b0fe64SMarian Balakowicz *cmd_end = *cmd_start + strlen(cmdline); 863b6b0fe64SMarian Balakowicz 864b6b0fe64SMarian Balakowicz debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); 865b6b0fe64SMarian Balakowicz 866b6b0fe64SMarian Balakowicz return (ulong)cmdline; 867b6b0fe64SMarian Balakowicz } 868b6b0fe64SMarian Balakowicz 869b6b0fe64SMarian Balakowicz /** 870b6b0fe64SMarian Balakowicz * get_boot_kbd - allocate and initialize kernel copy of board info 871b6b0fe64SMarian Balakowicz * @alloc_current: current boot allocation address (counting down 872b6b0fe64SMarian Balakowicz * from sp_limit) 873b6b0fe64SMarian Balakowicz * @kbd: double pointer to board info data 874b6b0fe64SMarian Balakowicz * 875b6b0fe64SMarian Balakowicz * get_boot_kbd() - allocates space for kernel copy of board info data. 876b6b0fe64SMarian Balakowicz * Space is allocated below provided alloc_current address and kernel 877b6b0fe64SMarian Balakowicz * board info is initialized with the current u-boot board info data. 878b6b0fe64SMarian Balakowicz * 879b6b0fe64SMarian Balakowicz * returns: 880b6b0fe64SMarian Balakowicz * alloc_current after kbd allocation 881b6b0fe64SMarian Balakowicz */ 882b6b0fe64SMarian Balakowicz ulong get_boot_kbd (ulong alloc_current, bd_t **kbd) 883b6b0fe64SMarian Balakowicz { 884b6b0fe64SMarian Balakowicz *kbd = (bd_t *) (((ulong)alloc_current - sizeof(bd_t)) & ~0xF); 885b6b0fe64SMarian Balakowicz **kbd = *(gd->bd); 886b6b0fe64SMarian Balakowicz 887b6b0fe64SMarian Balakowicz debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd); 888b6b0fe64SMarian Balakowicz 889b6b0fe64SMarian Balakowicz #if defined(DEBUG) && defined(CONFIG_CMD_BDI) 890b6b0fe64SMarian Balakowicz do_bdinfo(NULL, 0, 0, NULL); 891b6b0fe64SMarian Balakowicz #endif 892b6b0fe64SMarian Balakowicz 893b6b0fe64SMarian Balakowicz return (ulong)*kbd; 894ceaed2b1SMarian Balakowicz } 895ceaed2b1SMarian Balakowicz #endif /* CONFIG_PPC || CONFIG_M68K */ 8965ad03eb3SMarian Balakowicz 897f50433d6SMarian Balakowicz #if defined(CONFIG_FIT) 898f50433d6SMarian Balakowicz /*****************************************************************************/ 899f50433d6SMarian Balakowicz /* New uImage format routines */ 900f50433d6SMarian Balakowicz /*****************************************************************************/ 901f50433d6SMarian Balakowicz static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr, 902f50433d6SMarian Balakowicz ulong *addr, const char **name) 903f50433d6SMarian Balakowicz { 904f50433d6SMarian Balakowicz const char *sep; 905f50433d6SMarian Balakowicz 906f50433d6SMarian Balakowicz *addr = addr_curr; 907f50433d6SMarian Balakowicz *name = NULL; 908f50433d6SMarian Balakowicz 909f50433d6SMarian Balakowicz sep = strchr (spec, sepc); 910f50433d6SMarian Balakowicz if (sep) { 911f50433d6SMarian Balakowicz if (sep - spec > 0) 912f50433d6SMarian Balakowicz *addr = simple_strtoul (spec, NULL, 16); 913f50433d6SMarian Balakowicz 914f50433d6SMarian Balakowicz *name = sep + 1; 915f50433d6SMarian Balakowicz return 1; 916f50433d6SMarian Balakowicz } 917f50433d6SMarian Balakowicz 918f50433d6SMarian Balakowicz return 0; 919f50433d6SMarian Balakowicz } 920f50433d6SMarian Balakowicz 921f50433d6SMarian Balakowicz /** 922f50433d6SMarian Balakowicz * fit_parse_conf - parse FIT configuration spec 923f50433d6SMarian Balakowicz * @spec: input string, containing configuration spec 924f50433d6SMarian Balakowicz * @add_curr: current image address (to be used as a possible default) 925f50433d6SMarian Balakowicz * @addr: pointer to a ulong variable, will hold FIT image address of a given 926f50433d6SMarian Balakowicz * configuration 927f50433d6SMarian Balakowicz * @conf_name double pointer to a char, will hold pointer to a configuration 928f50433d6SMarian Balakowicz * unit name 929f50433d6SMarian Balakowicz * 930f50433d6SMarian Balakowicz * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>, 931f50433d6SMarian Balakowicz * where <addr> is a FIT image address that contains configuration 932f50433d6SMarian Balakowicz * with a <conf> unit name. 933f50433d6SMarian Balakowicz * 934f50433d6SMarian Balakowicz * Address part is optional, and if omitted default add_curr will 935f50433d6SMarian Balakowicz * be used instead. 936f50433d6SMarian Balakowicz * 937f50433d6SMarian Balakowicz * returns: 938f50433d6SMarian Balakowicz * 1 if spec is a valid configuration string, 939f50433d6SMarian Balakowicz * addr and conf_name are set accordingly 940f50433d6SMarian Balakowicz * 0 otherwise 941f50433d6SMarian Balakowicz */ 942f50433d6SMarian Balakowicz inline int fit_parse_conf (const char *spec, ulong addr_curr, 943f50433d6SMarian Balakowicz ulong *addr, const char **conf_name) 944f50433d6SMarian Balakowicz { 945f50433d6SMarian Balakowicz return fit_parse_spec (spec, '#', addr_curr, addr, conf_name); 946f50433d6SMarian Balakowicz } 947f50433d6SMarian Balakowicz 948f50433d6SMarian Balakowicz /** 949f50433d6SMarian Balakowicz * fit_parse_subimage - parse FIT subimage spec 950f50433d6SMarian Balakowicz * @spec: input string, containing subimage spec 951f50433d6SMarian Balakowicz * @add_curr: current image address (to be used as a possible default) 952f50433d6SMarian Balakowicz * @addr: pointer to a ulong variable, will hold FIT image address of a given 953f50433d6SMarian Balakowicz * subimage 954f50433d6SMarian Balakowicz * @image_name: double pointer to a char, will hold pointer to a subimage name 955f50433d6SMarian Balakowicz * 956f50433d6SMarian Balakowicz * fit_parse_subimage() expects subimage spec in the for of 957f50433d6SMarian Balakowicz * [<addr>]:<subimage>, where <addr> is a FIT image address that contains 958f50433d6SMarian Balakowicz * subimage with a <subimg> unit name. 959f50433d6SMarian Balakowicz * 960f50433d6SMarian Balakowicz * Address part is optional, and if omitted default add_curr will 961f50433d6SMarian Balakowicz * be used instead. 962f50433d6SMarian Balakowicz * 963f50433d6SMarian Balakowicz * returns: 964f50433d6SMarian Balakowicz * 1 if spec is a valid subimage string, 965f50433d6SMarian Balakowicz * addr and image_name are set accordingly 966f50433d6SMarian Balakowicz * 0 otherwise 967f50433d6SMarian Balakowicz */ 968f50433d6SMarian Balakowicz inline int fit_parse_subimage (const char *spec, ulong addr_curr, 969f50433d6SMarian Balakowicz ulong *addr, const char **image_name) 970f50433d6SMarian Balakowicz { 971f50433d6SMarian Balakowicz return fit_parse_spec (spec, ':', addr_curr, addr, image_name); 972f50433d6SMarian Balakowicz } 973d5934ad7SMarian Balakowicz 974f50433d6SMarian Balakowicz #endif /* CONFIG_FIT */ 975f50433d6SMarian Balakowicz 976b6b0fe64SMarian Balakowicz #endif /* USE_HOSTCC */ 977