image.c
来自「uboot详细解读可用启动引导LINUX2.6内核」· C语言 代码 · 共 2,365 行 · 第 1/5 页
C
2,365 行
/* * (C) Copyright 2008 Semihalf * * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#ifndef USE_HOSTCC#include <common.h>#include <watchdog.h>#ifdef CONFIG_SHOW_BOOT_PROGRESS#include <status_led.h>#endif#ifdef CONFIG_HAS_DATAFLASH#include <dataflash.h>#endif#ifdef CONFIG_LOGBUFFER#include <logbuff.h>#endif#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)#include <rtc.h>#endif#include <image.h>#if defined(CONFIG_FIT) || defined (CONFIG_OF_LIBFDT)#include <fdt.h>#include <libfdt.h>#include <fdt_support.h>#endif#if defined(CONFIG_FIT)#include <u-boot/md5.h>#include <sha1.h>static int fit_check_ramdisk (const void *fit, int os_noffset, uint8_t arch, int verify);#endif#ifdef CONFIG_CMD_BDIextern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);#endifDECLARE_GLOBAL_DATA_PTR;static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, int verify);#else#include "mkimage.h"#include <u-boot/md5.h>#include <time.h>#include <image.h>#endif /* !USE_HOSTCC*/typedef struct table_entry { int id; /* as defined in image.h */ char *sname; /* short (input) name */ char *lname; /* long (output) name */} table_entry_t;static table_entry_t uimage_arch[] = { { IH_ARCH_INVALID, NULL, "Invalid ARCH", }, { IH_ARCH_ALPHA, "alpha", "Alpha", }, { IH_ARCH_ARM, "arm", "ARM", }, { IH_ARCH_I386, "x86", "Intel x86", }, { IH_ARCH_IA64, "ia64", "IA64", }, { IH_ARCH_M68K, "m68k", "M68K", }, { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", }, { IH_ARCH_MIPS, "mips", "MIPS", }, { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", }, { IH_ARCH_NIOS, "nios", "NIOS", }, { IH_ARCH_NIOS2, "nios2", "NIOS II", }, { IH_ARCH_PPC, "powerpc", "PowerPC", }, { IH_ARCH_PPC, "ppc", "PowerPC", }, { IH_ARCH_S390, "s390", "IBM S390", }, { IH_ARCH_SH, "sh", "SuperH", }, { IH_ARCH_SPARC, "sparc", "SPARC", }, { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", }, { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", }, { IH_ARCH_AVR32, "avr32", "AVR32", }, { -1, "", "", },};static table_entry_t uimage_os[] = { { IH_OS_INVALID, NULL, "Invalid OS", },#if defined(CONFIG_ARTOS) || defined(USE_HOSTCC) { IH_OS_ARTOS, "artos", "ARTOS", },#endif { IH_OS_LINUX, "linux", "Linux", },#if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) { IH_OS_LYNXOS, "lynxos", "LynxOS", },#endif { IH_OS_NETBSD, "netbsd", "NetBSD", }, { IH_OS_RTEMS, "rtems", "RTEMS", }, { IH_OS_U_BOOT, "u-boot", "U-Boot", },#if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC) { IH_OS_QNX, "qnx", "QNX", }, { IH_OS_VXWORKS, "vxworks", "VxWorks", },#endif#ifdef USE_HOSTCC { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, { IH_OS_DELL, "dell", "Dell", }, { IH_OS_ESIX, "esix", "Esix", }, { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, { IH_OS_IRIX, "irix", "Irix", }, { IH_OS_NCR, "ncr", "NCR", }, { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, { IH_OS_PSOS, "psos", "pSOS", }, { IH_OS_SCO, "sco", "SCO", }, { IH_OS_SOLARIS, "solaris", "Solaris", }, { IH_OS_SVR4, "svr4", "SVR4", },#endif { -1, "", "", },};static table_entry_t uimage_type[] = { { IH_TYPE_INVALID, NULL, "Invalid Image", }, { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, { IH_TYPE_MULTI, "multi", "Multi-File Image", }, { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, { IH_TYPE_SCRIPT, "script", "Script", }, { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, { -1, "", "", },};static table_entry_t uimage_comp[] = { { IH_COMP_NONE, "none", "uncompressed", }, { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, { IH_COMP_GZIP, "gzip", "gzip compressed", }, { -1, "", "", },};uint32_t crc32 (uint32_t, const unsigned char *, uint);uint32_t crc32_wd (uint32_t, const unsigned char *, uint, uint);static void genimg_print_size (uint32_t size);#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)static void genimg_print_time (time_t timestamp);#endif/*****************************************************************************//* Legacy format routines *//*****************************************************************************/int image_check_hcrc (image_header_t *hdr){ ulong hcrc; ulong len = image_get_header_size (); image_header_t header; /* Copy header so we can blank CRC field for re-calculation */ memmove (&header, (char *)hdr, image_get_header_size ()); image_set_hcrc (&header, 0); hcrc = crc32 (0, (unsigned char *)&header, len); return (hcrc == image_get_hcrc (hdr));}int image_check_dcrc (image_header_t *hdr){ ulong data = image_get_data (hdr); ulong len = image_get_data_size (hdr); ulong dcrc = crc32_wd (0, (unsigned char *)data, len, CHUNKSZ_CRC32); return (dcrc == image_get_dcrc (hdr));}/** * image_multi_count - get component (sub-image) count * @hdr: pointer to the header of the multi component image * * image_multi_count() returns number of components in a multi * component image. * * Note: no checking of the image type is done, caller must pass * a valid multi component image. * * returns: * number of components */ulong image_multi_count (image_header_t *hdr){ ulong i, count = 0; uint32_t *size; /* get start of the image payload, which in case of multi * component images that points to a table of component sizes */ size = (uint32_t *)image_get_data (hdr); /* count non empty slots */ for (i = 0; size[i]; ++i) count++; return count;}/** * image_multi_getimg - get component data address and size * @hdr: pointer to the header of the multi component image * @idx: index of the requested component * @data: pointer to a ulong variable, will hold component data address * @len: pointer to a ulong variable, will hold component size * * image_multi_getimg() returns size and data address for the requested * component in a multi component image. * * Note: no checking of the image type is done, caller must pass * a valid multi component image. * * returns: * data address and size of the component, if idx is valid * 0 in data and len, if idx is out of range */void image_multi_getimg (image_header_t *hdr, ulong idx, ulong *data, ulong *len){ int i; uint32_t *size; ulong offset, count, img_data; /* get number of component */ count = image_multi_count (hdr); /* get start of the image payload, which in case of multi * component images that points to a table of component sizes */ size = (uint32_t *)image_get_data (hdr); /* get address of the proper component data start, which means * skipping sizes table (add 1 for last, null entry) */ img_data = image_get_data (hdr) + (count + 1) * sizeof (uint32_t); if (idx < count) { *len = uimage_to_cpu (size[idx]); offset = 0; /* go over all indices preceding requested component idx */ for (i = 0; i < idx; i++) { /* add up i-th component size, rounding up to 4 bytes */ offset += (uimage_to_cpu (size[i]) + 3) & ~3 ; } /* calculate idx-th component data address */ *data = img_data + offset; } else { *len = 0; *data = 0; }}static void image_print_type (image_header_t *hdr){ const char *os, *arch, *type, *comp; os = genimg_get_os_name (image_get_os (hdr)); arch = genimg_get_arch_name (image_get_arch (hdr)); type = genimg_get_type_name (image_get_type (hdr)); comp = genimg_get_comp_name (image_get_comp (hdr)); printf ("%s %s %s (%s)\n", arch, os, type, comp);}/** * image_print_contents - prints out the contents of the legacy format image * @hdr: pointer to the legacy format image header * @p: pointer to prefix string * * image_print_contents() formats a multi line legacy image contents description. * The routine prints out all header fields followed by the size/offset data * for MULTI/SCRIPT images. * * returns: * no returned results */void image_print_contents (image_header_t *hdr){ const char *p;#ifdef USE_HOSTCC p = "";#else p = " ";#endif printf ("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name (hdr));#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) printf ("%sCreated: ", p); genimg_print_time ((time_t)image_get_time (hdr));#endif printf ("%sImage Type: ", p); image_print_type (hdr); printf ("%sData Size: ", p); genimg_print_size (image_get_data_size (hdr)); printf ("%sLoad Address: %08x\n", p, image_get_load (hdr)); printf ("%sEntry Point: %08x\n", p, image_get_ep (hdr)); if (image_check_type (hdr, IH_TYPE_MULTI) || image_check_type (hdr, IH_TYPE_SCRIPT)) { int i; ulong data, len; ulong count = image_multi_count (hdr); printf ("%sContents:\n", p); for (i = 0; i < count; i++) { image_multi_getimg (hdr, i, &data, &len); printf ("%s Image %d: ", p, i); genimg_print_size (len); if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) { /* * the user may need to know offsets * if planning to do something with * multiple files */ printf ("%s Offset = 0x%08lx\n", p, data); } } }}#ifndef USE_HOSTCC/** * image_get_ramdisk - get and verify ramdisk image * @rd_addr: ramdisk image start address * @arch: expected ramdisk architecture * @verify: checksum verification flag * * image_get_ramdisk() returns a pointer to the verified ramdisk image * header. Routine receives image start address and expected architecture * flag. Verification done covers data and header integrity and os/type/arch * fields checking. * * If dataflash support is enabled routine checks for dataflash addresses * and handles required dataflash reads. * * returns: * pointer to a ramdisk image header, if image was found and valid * otherwise, return NULL */static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, int verify){ image_header_t *rd_hdr = (image_header_t *)rd_addr; if (!image_check_magic (rd_hdr)) { puts ("Bad Magic Number\n"); show_boot_progress (-10); return NULL; } if (!image_check_hcrc (rd_hdr)) { puts ("Bad Header Checksum\n"); show_boot_progress (-11); return NULL; } show_boot_progress (10); image_print_contents (rd_hdr); if (verify) { puts(" Verifying Checksum ... "); if (!image_check_dcrc (rd_hdr)) { puts ("Bad Data CRC\n"); show_boot_progress (-12); return NULL; } puts("OK\n"); } show_boot_progress (11); if (!image_check_os (rd_hdr, IH_OS_LINUX) || !image_check_arch (rd_hdr, arch) || !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { printf ("No Linux %s Ramdisk Image\n", genimg_get_arch_name(arch)); show_boot_progress (-13); return NULL; } return rd_hdr;}#endif /* !USE_HOSTCC *//*****************************************************************************//* Shared dual-format routines *//*****************************************************************************/#ifndef USE_HOSTCCint getenv_yesno (char *var){ char *s = getenv (var); return (s && (*s == 'n')) ? 0 : 1;}ulong getenv_bootm_low(void){ char *s = getenv ("bootm_low"); if (s) { ulong tmp = simple_strtoul (s, NULL, 16); return tmp; }#if defined(CFG_SDRAM_BASE) return CFG_SDRAM_BASE;#elif defined(CONFIG_ARM) return gd->bd->bi_dram[0].start;#else return 0;#endif}phys_size_t getenv_bootm_size(void){ char *s = getenv ("bootm_size"); if (s) { phys_size_t tmp;#ifdef CFG_64BIT_STRTOUL tmp = (phys_size_t)simple_strtoull (s, NULL, 16);#else tmp = (phys_size_t)simple_strtoul (s, NULL, 16);#endif return tmp; }#if defined(CONFIG_ARM) return gd->bd->bi_dram[0].size;#else return gd->bd->bi_memsize;#endif}void memmove_wd (void *to, void *from, size_t len, ulong chunksz){#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) while (len > 0) { size_t tail = (len > chunksz) ? chunksz : len; WATCHDOG_RESET (); memmove (to, from, tail); to += tail; from += tail; len -= tail; }#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ memmove (to, from, len);#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */}#endif /* !USE_HOSTCC */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?