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