From 29a08659f0508c6f82cbca1a5ba5f38ef04081e9 Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Sun, 14 Aug 2016 10:33:03 +0200 Subject: [PATCH] Cleanups in bootm command and related code Instead of selecting supported header type (standard U-Boot image or custom TP-Link) at compile time, from now both headers are supported. This allows to use both image types on all devices, which sometimes might be useful. Other changes: - clean up code style, use tab size = 8 - restore support for Multi-File image, used in some ZBT routers - add new TP-Link image header definition, get rid of old one - restore CRC checksum tests (for image header and data) - make image header information look better, include more data - remove bootd command, as it was only alias for boot command --- u-boot/common/cmd_bootm.c | 878 ++++++++++++++++++++-------------- u-boot/include/common.h | 14 +- u-boot/include/tpLinuxTag.h | 60 --- u-boot/include/tplink_image.h | 45 ++ 4 files changed, 567 insertions(+), 430 deletions(-) delete mode 100644 u-boot/include/tpLinuxTag.h create mode 100644 u-boot/include/tplink_image.h diff --git a/u-boot/common/cmd_bootm.c b/u-boot/common/cmd_bootm.c index b5072b7..627a09d 100644 --- a/u-boot/common/cmd_bootm.c +++ b/u-boot/common/cmd_bootm.c @@ -1,24 +1,8 @@ /* - * (C) Copyright 2000-2006 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Copyright (C) 2016 Piotr Dymacz + * Copyright (C) 2000-2006 Wolfgang Denk, DENX Software Engineering, * - * 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 + * SPDX-License-Identifier: GPL-2.0 */ /* @@ -27,403 +11,577 @@ #include #include #include +#include #include #include #include #include #include -DECLARE_GLOBAL_DATA_PTR; - #ifdef CFG_HUSH_PARSER #include #endif -/* cmd_boot.c */ -extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - -/* net.c */ -extern void eth_halt(void); - #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) #include #endif -/* - * Continue booting an OS image; caller already has: - * - copied image header to global variable `header' - * - checked header magic number, checksums (both header & image), - * - verified image architecture (PPC) and type (KERNEL or MULTI), - * - loaded (first part of) image to header load address, - * - disabled interrupts. - */ +DECLARE_GLOBAL_DATA_PTR; + extern void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +extern void eth_halt(void); -#ifdef CONFIG_SILENT_CONSOLE -static void fixup_silent_linux(void); -#endif +/* U-Boot type image header */ +image_header_t header; -#if (CONFIG_COMMANDS & CFG_CMD_IMI) -static int image_info(unsigned long addr); -#endif +/* Default load address */ +u32 load_addr = CFG_LOAD_ADDR; -image_header_t header; -ulong load_addr = CFG_LOAD_ADDR; /* default load address */ +#define TPL_ALIGN_SIZE 21 +#define UBOOT_ALIGN_SIZE 14 -#ifdef CONFIG_TPLINK_IMAGE_HEADER -void fake_image_header(image_header_t *hdr, tplink_image_header_t *tpl_hdr){ - memset(hdr, 0, sizeof(image_header_t)); +/* + * Clears console variable from command line + */ +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux(void) +{ + char buf[256]; + char *cmdline, *end, *start; - /* Build new header */ - hdr->ih_magic = htonl(IH_MAGIC); - hdr->ih_hcrc = 0; - hdr->ih_time = 0; - hdr->ih_size = htonl(tpl_hdr->kernelLen); - hdr->ih_load = htonl(tpl_hdr->kernelTextAddr); - hdr->ih_ep = htonl(tpl_hdr->kernelEntryPoint); - hdr->ih_dcrc = 0; - hdr->ih_os = IH_OS_LINUX; - hdr->ih_arch = IH_CPU_MIPS; - hdr->ih_type = IH_TYPE_KERNEL; - hdr->ih_comp = IH_COMP_LZMA; - - strncpy((char *)hdr->ih_name, (char *)tpl_hdr->signiture_1, IH_NMLEN); -} -#endif /* CONFIG_TPLINK_IMAGE_HEADER */ + /* Only fix cmdline when requested */ + if (!(gd->flags & GD_FLG_SILENT)) { + return; + } -int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ - ulong addr, data, len; - uint unc_len = CFG_BOOTM_LEN; - int i; - image_header_t *hdr = &header; -#ifdef CONFIG_TPLINK_IMAGE_HEADER - tplink_image_header_t *fileTag; -#endif + cmdline = getenv("bootargs"); - if(argc < 2){ - addr = load_addr; + if (cmdline) { + if ((start = strstr(cmdline, "console=")) != NULL) { + end = strchr(start, ' '); + strncpy(buf, cmdline, (start - cmdline + 8)); + + if (end) { + strcpy(buf + (start - cmdline + 8), end); + } else { + buf[start - cmdline + 8] = '\0'; + } + } else { + strcpy(buf, cmdline); + strcat(buf, " console="); + } } else { - addr = simple_strtoul(argv[1], NULL, 16); + strcpy(buf, "console="); } - printf("Booting image at: 0x%08lX\n", addr); + setenv("bootargs", buf); +} +#endif /* CONFIG_SILENT_CONSOLE */ -#ifndef CONFIG_TPLINK_IMAGE_HEADER - memmove(&header, (char *)addr, sizeof(image_header_t)); - print_image_hdr(hdr); +/* + * Prints information about TP-Link + * firmware format from header + */ +static void print_tpl_ih_v1(tplink_image_header_t *hdr) +{ + puts("\n"); - data = addr + sizeof(image_header_t); -#else - fileTag = (tplink_image_header_t *)addr; - print_image_hdr(fileTag); + /* Image/vendor name */ + printf(" %-*s ", TPL_ALIGN_SIZE, "Vendor/image name:"); + printf("%.*s %.*s\n", + sizeof(hdr->ih_vendor), hdr->ih_vendor, + sizeof(hdr->ih_info), hdr->ih_info); + + /* Version (for vendor firmware only) */ + if (hdr->ih_fw_ver_hi > 0) { + printf(" %-*s ", TPL_ALIGN_SIZE, "Firmware version:"); + printf("%d.%d.%d\n", + ntohl(hdr->ih_fw_ver_hi), + ntohl(hdr->ih_fw_ver_mid), + ntohl(hdr->ih_fw_ver_lo)); + } - fake_image_header(hdr, fileTag); + /* Hardware id */ + printf(" %-*s ", TPL_ALIGN_SIZE, "Hardware ID:"); + printf("0x%X\n", ntohl(hdr->ih_hw_id)); - data = addr + TAG_LEN; -#endif /* !CONFIG_TPLINK_IMAGE_HEADER */ + /* Sizes of firmware parts */ + printf(" %-*s ", TPL_ALIGN_SIZE, "Whole image size:"); + print_size(ntohl(hdr->ih_fw_len), " "); + printf("(%d bytes)\n", ntohl(hdr->ih_fw_len)); - len = ntohl(hdr->ih_size); + printf(" %-*s ", TPL_ALIGN_SIZE, "Kernel size:"); + print_size(ntohl(hdr->ih_kernel_len), " "); + printf("(%d bytes)\n", ntohl(hdr->ih_kernel_len)); - /* - * We have reached the point of no return: we are going to - * overwrite all exception vector code, so we cannot easily - * recover from any failures any more... - */ -#ifdef CONFIG_NETCONSOLE - /* - * Stop the ethernet stack if NetConsole could have - * left it up - */ - eth_halt(); -#endif + printf(" %-*s ", TPL_ALIGN_SIZE, "Rootfs size:"); + print_size(ntohl(hdr->ih_rootfs_len), " "); + printf("(%d bytes)\n", ntohl(hdr->ih_rootfs_len)); - /* TODO: should we flush caches for kernel? */ - /* - * Flush everything, restore caches for linux - */ - //mips_cache_flush(); - //mips_icache_flush_ix(); + printf(" %-*s ", TPL_ALIGN_SIZE, "Kernel load address:"); + printf("0x%08X\n", ntohl(hdr->ih_kernel_load)); - /* XXX - this causes problems when booting from flash */ - /* dcache_disable(); */ + printf(" %-*s ", TPL_ALIGN_SIZE, "Kernel entry point:"); + printf("0x%08X\n", ntohl(hdr->ih_kernel_ep)); - /* case IH_COMP_LZMA:*/ - puts("Uncompressing kernel image... "); + /* TODO: MD5 sum verify */ - i = lzma_inflate((unsigned char *)data, len, (unsigned char*)ntohl(hdr->ih_load), (int *)&unc_len); + puts("\n"); +} - if(i != LZMA_RESULT_OK){ - printf("## Error: LZMA error num: %d\n", i); - return(-1); +/* + * Returns image type in text + */ +static char *ih_img_type(uint8_t img) +{ + switch (img) { + case IH_TYPE_KERNEL: + return "Kernel"; + case IH_TYPE_MULTI: + return "Multi-File"; +/* + case IH_TYPE_INVALID: + return "Invalid"; + case IH_TYPE_STANDALONE: + return "Standalone program"; + case IH_TYPE_RAMDISK: + return "RAMDisk"; + case IH_TYPE_FIRMWARE: + return "Firmware"; + case IH_TYPE_SCRIPT: + return "Script"; +*/ + default: + return "unknown"; } +} - puts("OK!\n"); +/* + * Returns architecture type in text + */ +static char *ih_arch_type(uint8_t arch) +{ + switch (arch) { + case IH_CPU_MIPS: + return "MIPS"; +/* + case IH_CPU_INVALID: + return "Invalid CPU"; + case IH_CPU_ALPHA: + return "Alpha"; + case IH_CPU_ARM: + return "ARM"; + case IH_CPU_I386: + return "Intel x86"; + case IH_CPU_IA64: + return "IA64"; + case IH_CPU_MIPS64: + return "MIPS 64-bit"; + case IH_CPU_PPC: + return "PowerPC"; + case IH_CPU_S390: + return "IBM S390"; + case IH_CPU_SH: + return "SuperH"; + case IH_CPU_SPARC: + return "SPARC"; + case IH_CPU_SPARC64: + return "SPARC 64-bit"; + case IH_CPU_M68K: + return "M68K"; + case IH_CPU_MICROBLAZE: + return "Microblaze"; + case IH_CPU_NIOS: + return "Nios"; + case IH_CPU_NIOS2: + return "Nios-II"; +*/ + default: + return "unknown"; + } +} -#ifdef CONFIG_SILENT_CONSOLE - fixup_silent_linux(); +/* + * Returns compression type in text + */ +static char *ih_comp_type(uint8_t comp) +{ + switch (comp) { + case IH_COMP_LZMA: + return "LZMA"; +/* + case IH_COMP_NONE: + return "none"; + case IH_COMP_GZIP: + return "GZIP"; + case IH_COMP_BZIP2: + return "BZIP2"; +*/ + default: + return "unknown"; + } +} + +/* + * Returns operating system type in text + */ +static char *ih_os_type(uint8_t os) +{ + switch (os) { + case IH_OS_LINUX: + return "Linux"; +/* + case IH_OS_INVALID: + return "Invalid OS"; + case IH_OS_NETBSD: + return "NetBSD"; + case IH_OS_VXWORKS: + return "VxWorks"; + case IH_OS_QNX: + return "QNX"; + case IH_OS_U_BOOT: + return "U-Boot"; + case IH_OS_RTEMS: + return "RTEMS"; +*/ + default: + return "unknown"; + } +} + +/* + * Prints information about standard + * U-Boot image format from header + */ +static void print_uboot_ih(image_header_t *hdr) +{ + int i; + u32 len; + u32 *len_ptr; +#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) + struct rtc_time tm; + time_t timestamp = (time_t)ntohl(hdr->ih_time); #endif - do_bootm_linux(cmdtp, flag, argc, argv); + puts("\n"); + + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Image name:"); + printf("%.*s\n", sizeof(hdr->ih_name), hdr->ih_name); -#ifdef DEBUG - puts("\n## Error: control returned to monitor - resetting...\n"); - do_reset(cmdtp, flag, argc, argv); +#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Build date:"); + to_tm(timestamp, &tm); + printf("%4d-%02d-%02d %02d:%02d:%02d UTC\n", + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); #endif - return(1); + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Architecture:"); + printf("%s\n", ih_arch_type(hdr->ih_arch)); + + printf(" %-*s ", UBOOT_ALIGN_SIZE, "OS/image type:"); + printf("%s %s\n", ih_os_type(hdr->ih_os), ih_img_type(hdr->ih_type)); + + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Compression:"); + printf("%s\n", ih_comp_type(hdr->ih_comp)); + + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Data size:"); + print_size(ntohl(hdr->ih_size), " "); + printf("(%d bytes)\n", ntohl(hdr->ih_size)); + + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Load address:"); + printf("0x%08X\n", ntohl(hdr->ih_load)); + + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Entry point:"); + printf("0x%08X\n", ntohl(hdr->ih_ep)); + + if (hdr->ih_type == IH_TYPE_MULTI) { + len_ptr = (u32 *)((u32)hdr + sizeof(image_header_t)); + + printf("\n %-*s\n", UBOOT_ALIGN_SIZE, "Multi-File:"); + + for (i = 0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) { + puts(" > "); + print_size(len, " "); + printf("(%d bytes)\n", len); + } + } + + puts("\n"); } -U_BOOT_CMD(bootm, 2, 1, do_bootm, "boot application image from memory\n", "[addr]\n" -"\t- boot application image stored in memory at address 'addr'\n"); +/* + * Verifies U-Boot image data checksum + */ +static int ih_data_crc(u32 addr, image_header_t *hdr, int tpl_type, int verify) +{ + int ret = 0; -#ifdef CONFIG_SILENT_CONSOLE -static void fixup_silent_linux(){ - char buf[256], *start, *end; - char *cmdline = getenv("bootargs"); + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Data CRC..."); - /* Only fix cmdline when requested */ - if(!(gd->flags & GD_FLG_SILENT)){ - return; + if (tpl_type == 0 && verify == 1) { + if (tinf_crc32((u8 *)addr, ntohl(hdr->ih_size)) + != ntohl(hdr->ih_dcrc)) { + puts("ERROR\n\n"); + ret = 1; + } else { + puts("OK!\n"); + } + } else { + puts("skipped\n"); } -#ifdef DEBUG - printf("before silent fix-up: %s\n", cmdline); -#endif + return ret; +} - if(cmdline){ - if((start = strstr(cmdline, "console=")) != NULL){ - end = strchr(start, ' '); - strncpy(buf, cmdline, (start - cmdline + 8)); - if(end){ - strcpy(buf + (start - cmdline + 8), end); - } else { - buf[start - cmdline + 8] = '\0'; - } +/* + * Verifies U-Boot image header checksum + */ +static int ih_header_crc(image_header_t *hdr, int tpl_type) +{ + u32 crc; + int ret = 0; + + printf(" %-*s ", UBOOT_ALIGN_SIZE, "Header CRC..."); + + if (tpl_type == 0) { + crc = ntohl(hdr->ih_hcrc); + hdr->ih_hcrc = 0; + + if (tinf_crc32((u8 *)hdr, sizeof(image_header_t)) != crc) { + puts("ERROR\n\n"); + ret = 1; } else { - strcpy(buf, cmdline); - strcat(buf, " console="); + puts("OK!\n"); } + + hdr->ih_hcrc = crc; } else { - strcpy(buf, "console="); + puts("skipped\n"); } - setenv("bootargs", buf); - debug("after silent fix-up: %s\n", buf); + return ret; } -#endif /* CONFIG_SILENT_CONSOLE */ -#ifndef CONFIG_TPLINK_IMAGE_HEADER -static void print_type(image_header_t *hdr){ - char *os, *arch, *type, *comp; - - switch(hdr->ih_os){ - case IH_OS_INVALID: - os = "Invalid OS"; - break; - case IH_OS_NETBSD: - os = "NetBSD"; - break; - case IH_OS_LINUX: - os = "Linux"; - break; - case IH_OS_VXWORKS: - os = "VxWorks"; - break; - case IH_OS_QNX: - os = "QNX"; - break; - case IH_OS_U_BOOT: - os = "U-Boot"; - break; - case IH_OS_RTEMS: - os = "RTEMS"; - break; - default: - os = "Unknown OS"; - break; +/* + * Converts TP-Link header to stanard + * U-Boot image format header + */ +static void tpl_to_uboot_header(image_header_t *hdr, + tplink_image_header_t *tpl_hdr) +{ + memset(hdr, 0, sizeof(image_header_t)); + + /* Set only needed values */ + hdr->ih_hcrc = 0; + hdr->ih_dcrc = 0; + + hdr->ih_ep = htonl(tpl_hdr->ih_kernel_ep); + hdr->ih_size = htonl(tpl_hdr->ih_kernel_len); + hdr->ih_load = htonl(tpl_hdr->ih_kernel_load); + + hdr->ih_os = IH_OS_LINUX; + hdr->ih_arch = IH_CPU_MIPS; + hdr->ih_type = IH_TYPE_KERNEL; + hdr->ih_comp = IH_COMP_LZMA; +} + +int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *s; + u32 *len_ptr; + u32 addr, data, len; + int i, tpl_type, verify; + u32 unc_len = CFG_BOOTM_LEN; + image_header_t *hdr = &header; + tplink_image_header_t *tpl_hdr; + + /* + * By default don't verify data CRC checksum, + * but allow to enable it, using environment + **/ + s = getenv("verify_data"); + verify = (s && (*s == 'y')) ? 1 : 0; + + if (argc < 2) { + addr = load_addr; + } else { + addr = simple_strtoul(argv[1], NULL, 16); } - switch(hdr->ih_arch){ - case IH_CPU_INVALID: - arch = "Invalid CPU"; - break; - case IH_CPU_ALPHA: - arch = "Alpha"; - break; - case IH_CPU_ARM: - arch = "ARM"; - break; - case IH_CPU_I386: - arch = "Intel x86"; - break; - case IH_CPU_IA64: - arch = "IA64"; - break; - case IH_CPU_MIPS: - arch = "MIPS"; - break; - case IH_CPU_MIPS64: - arch = "MIPS 64 Bit"; - break; - case IH_CPU_PPC: - arch = "PowerPC"; - break; - case IH_CPU_S390: - arch = "IBM S390"; - break; - case IH_CPU_SH: - arch = "SuperH"; - break; - case IH_CPU_SPARC: - arch = "SPARC"; - break; - case IH_CPU_SPARC64: - arch = "SPARC 64 Bit"; - break; - case IH_CPU_M68K: - arch = "M68K"; - break; - case IH_CPU_MICROBLAZE: - arch = "Microblaze"; - break; - case IH_CPU_NIOS: - arch = "Nios"; - break; - case IH_CPU_NIOS2: - arch = "Nios-II"; - break; - default: - arch = "Unknown Architecture"; - break; + printf("Booting image from 0x%08lX...\n", addr); + + /* Check what header type we have */ + memmove(&data, (char *)addr, sizeof(u32)); + tpl_type = 0; + + switch (ntohl(data)) { + case TPL_IH_VERSION_V1: + tpl_type = 1; + + tpl_hdr = (tplink_image_header_t *)addr; + print_tpl_ih_v1(tpl_hdr); + + /* Convert to general format */ + tpl_to_uboot_header(hdr, tpl_hdr); + break; + case IH_MAGIC: + print_uboot_ih((image_header_t *)addr); + memmove(&header, (char *)addr, sizeof(image_header_t)); + break; + case TPL_IH_VERSION_V2: + case TPL_IH_VERSION_V3: + default: + puts("## Error: unsupported image header\n"); + return 1; } - switch(hdr->ih_type){ - case IH_TYPE_INVALID: - type = "Invalid Image"; - break; - case IH_TYPE_STANDALONE: - type = "Standalone Program"; - break; - case IH_TYPE_KERNEL: - type = "Kernel Image"; - break; - case IH_TYPE_RAMDISK: - type = "RAMDisk Image"; - break; - case IH_TYPE_MULTI: - type = "Multi-File Image"; - break; - case IH_TYPE_FIRMWARE: - type = "Firmware"; - break; - case IH_TYPE_SCRIPT: - type = "Script"; - break; - default: - type = "Unknown Image"; - break; + /* Always verify header CRC */ + if (ih_header_crc(hdr, tpl_type) != 0) { + puts("## Error: header checksum mismatch!\n"); + return 1; } - switch(hdr->ih_comp){ - case IH_COMP_NONE: - comp = "uncompressed"; - break; - case IH_COMP_GZIP: - comp = "gzip compressed"; - break; - case IH_COMP_BZIP2: - comp = "bzip2 compressed"; - break; - case IH_COMP_LZMA: - comp = "lzma compressed"; - break; - default: - comp = "unknown compression"; - break; + /* And data if enabled */ + if (tpl_type) { + data = addr + sizeof(tplink_image_header_t); + } else { + data = addr + sizeof(image_header_t); } - printf("%s %s %s (%s)", arch, os, type, comp); -} + if (ih_data_crc(data, hdr, tpl_type, verify) != 0) { + puts("## Error: data checksum mismatch!\n"); + return 1; + } -void print_image_hdr(image_header_t *hdr){ -#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) - time_t timestamp = (time_t)ntohl(hdr->ih_time); - struct rtc_time tm; -#endif + puts("\n"); - printf("\n Image name: %.*s\n", IH_NMLEN, hdr->ih_name); + len = ntohl(hdr->ih_size); + len_ptr = (u32 *)data; -#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) - to_tm(timestamp, &tm); - printf(" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); -#endif /* CFG_CMD_DATE, CONFIG_TIMESTAMP */ + /* We support only MIPS */ + if (hdr->ih_arch != IH_CPU_MIPS) { + puts("## Error: unsupported architecture!\n"); + return 1; + } + + /* Image type... */ + switch (hdr->ih_type) { + case IH_TYPE_KERNEL: + break; + case IH_TYPE_MULTI: + /* OS kernel is always in first image */ + len = ntohl(len_ptr[0]); + data += 8; + + /* Move over list to first image */ + for (i = 1; len_ptr[i]; ++i) + data += 4; + + break; + default: + puts("## Error: unsupported image type!\n"); + return 1; + } - puts(" Image type: "); - print_type(hdr); + /* + * We have reached the point of no return: we are going to + * overwrite all exception vector code, so we cannot easily + * recover from any failures any more... + */ - printf("\n Data size: %d Bytes = ", ntohl(hdr->ih_size)); - print_size(ntohl(hdr->ih_size), "\n"); +#ifdef CONFIG_NETCONSOLE + /* + * Stop the ethernet stack if NetConsole could have + * left it up + */ + puts("Stopping network... "); + eth_halt(); + puts("OK!\n"); +#endif - printf(" Load address: 0x%08X\n Entry point: 0x%08X\n", ntohl(hdr->ih_load), ntohl(hdr->ih_ep)); + /* TODO: should we flush caches for kernel? */ + /* + * Flush everything, restore caches for linux + */ + //mips_cache_flush(); + //mips_icache_flush_ix(); + + /* XXX - this causes problems when booting from flash */ + /* dcache_disable(); */ - if(hdr->ih_type == IH_TYPE_MULTI){ - int i; - ulong len; - ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t)); + /* Compression type... */ + switch (hdr->ih_comp) { + case IH_COMP_LZMA: + printf("Uncompressing %s... ", ih_img_type(hdr->ih_type)); - puts(" Contents:\n"); + /* Try to extract LZMA data... */ + i = lzma_inflate((u8 *)data, len, + (u8 *)ntohl(hdr->ih_load), (int *)&unc_len); - for(i = 0; (len = ntohl(*len_ptr)); ++i, ++len_ptr){ - printf(" Image %d: %8ld Bytes = ", i, len); - print_size(len, "\n"); + /* TODO: more verbose LZMA errors */ + if (i != LZMA_RESULT_OK) { + puts("ERROR\n"); + printf("## Error: LZMA error '%d'!\n", i); + return 1; } + + puts("OK!\n"); + break; + default: + printf("## Error: unsupported compression type '%s'!\n", + ih_comp_type(hdr->ih_comp)); + + return 1; } - puts("\n"); -} -#else -void print_image_hdr(tplink_image_header_t *hdr){ - printf("\n Image name: %.*s %.*s\n", SIG_LEN, hdr->signiture_1, SIG_LEN_2, hdr->signiture_2); - puts(" Image type: MIPS Linux Kernel Image (lzma compressed)\n"); - printf(" Data size: %d Bytes = ", ntohl(hdr->kernelLen)); - print_size(ntohl(hdr->kernelLen), "\n"); - printf(" Load address: 0x%08X\n Entry point: 0x%08X\n\n", ntohl(hdr->kernelTextAddr), ntohl(hdr->kernelEntryPoint)); +#ifdef CONFIG_SILENT_CONSOLE + fixup_silent_linux(); +#endif + + do_bootm_linux(cmdtp, flag, argc, argv); + + return 1; } -#endif /* !CONFIG_TPLINK_IMAGE_HEADER */ + +U_BOOT_CMD(bootm, 2, 1, do_bootm, + "boot application image from memory\n", "[addr]\n" + "\t- boot application image stored in memory at address 'addr'\n"); #if (CONFIG_COMMANDS & CFG_CMD_BOOTD) -int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ - int rcode = 0; +int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ #ifndef CFG_HUSH_PARSER - if(run_command (getenv ("bootcmd"), flag) < 0){ - rcode = 1; - } + if (run_command(getenv("bootcmd"), flag) < 0) + return 1; #else - if(parse_string_outer(getenv("bootcmd"), FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0){ - rcode = 1; - } + if (parse_string_outer(getenv("bootcmd"), + FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) + return 1; #endif - return(rcode); -} - -U_BOOT_CMD(boot, 1, 1, do_bootd, "boot default, i.e., run 'bootcmd'\n", NULL); -/* keep old command name "bootd" for backward compatibility */ -U_BOOT_CMD(bootd, 1, 1, do_bootd, "boot default, i.e., run 'bootcmd'\n", NULL); + return 0; +} +U_BOOT_CMD(boot, 1, 1, do_bootd, "boot default, run 'bootcmd'\n", NULL); #endif /* CONFIG_COMMANDS & CFG_CMD_BOOTD */ #if (CONFIG_COMMANDS & CFG_CMD_IMI) -int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ - ulong addr; - int rcode = 0; +int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int tpl_type; + u32 addr, data; + image_header_t *hdr = &header; + tplink_image_header_t *tpl_hdr; - if (argc == 2){ + tpl_type = 0; + + if (argc == 2) { addr = simple_strtoul(argv[1], NULL, 16); - return image_info(addr); } else { #ifdef CFG_LONGHELP - if(cmdtp->help != NULL){ + if (cmdtp->help != NULL) { printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->help); } else { printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage); @@ -431,52 +589,56 @@ int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){ #else printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage); #endif - return(1); + return 1; } - return(rcode); -} - -static int image_info(ulong addr){ - ulong data, len, checksum; - image_header_t *hdr = &header; - printf("\nChecking image at 0x%08lX...\n", addr); - /* Copy header so we can blank CRC field for re-calculation */ - memmove(&header, (char *)addr, sizeof(image_header_t)); - - data = (ulong)&header; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if(tinf_crc32((uchar *)data, len) != checksum){ - puts("## Error: bad header checksum!\n"); + /* Check what header type we have */ + memmove(&data, (char *)addr, sizeof(u32)); + + switch (ntohl(data)) { + case TPL_IH_VERSION_V1: + tpl_type = 1; + + tpl_hdr = (tplink_image_header_t *)addr; + print_tpl_ih_v1(tpl_hdr); + break; + case IH_MAGIC: + print_uboot_ih((image_header_t *)addr); + memmove(&header, (char *)addr, sizeof(image_header_t)); + break; + case TPL_IH_VERSION_V2: + case TPL_IH_VERSION_V3: + default: + puts("## Error: unsupported image header\n"); return 1; } - /* for multi-file images we need the data part, too */ - print_image_hdr((image_header_t *)addr); - - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); + /* Always verify header CRC */ + if (ih_header_crc(hdr, tpl_type) != 0) { + puts("## Error: header checksum mismatch!\n"); + return 1; + } - puts(" Verifying checksum... "); + /* And data.. here always */ + if (tpl_type) { + data = addr + sizeof(tplink_image_header_t); + } else { + data = addr + sizeof(image_header_t); + } - if(tinf_crc32((uchar *)data, len) != ntohl(hdr->ih_dcrc)){ - puts("bad data CRC!\n"); - return(1); + if (ih_data_crc(data, hdr, tpl_type, 1) != 0) { + puts("## Error: data checksum mismatch!\n"); + return 1; } - puts("OK!\n\n"); + puts("\n"); - return(0); + return 0; } -U_BOOT_CMD(iminfo, 2, 1, do_iminfo, "print firmware header\n", "address\n" - "\t- print header information for firmware image startting at address 'address'\n" -); - -#endif /* CFG_CMD_IMI */ +U_BOOT_CMD(iminfo, 2, 1, do_iminfo, + "print firmware header\n", "address\n" + "\t- print header information for image at 'address'\n"); +#endif /* CFG_CMD_IMI */ diff --git a/u-boot/include/common.h b/u-boot/include/common.h index 0a00827..5873fa4 100644 --- a/u-boot/include/common.h +++ b/u-boot/include/common.h @@ -199,18 +199,8 @@ void flash_perror (int); /* common/cmd_autoscript.c */ int autoscript (ulong addr); -/* - * Only TP-Link OFW and OpenWrt for TP-Link routers - * use different (simply) image header - */ -#ifdef CONFIG_TPLINK_IMAGE_HEADER -#include "tpLinuxTag.h" -void print_image_hdr(tplink_image_header_t *hdr); -#else -void print_image_hdr(image_header_t *hdr); -#endif /* CONFIG_TPLINK_IMAGE_HEADER */ - -extern ulong load_addr; /* Default Load Address */ +/* Default Load Address */ +extern u32 load_addr; /* common/cmd_nvedit.c */ int env_init (void); diff --git a/u-boot/include/tpLinuxTag.h b/u-boot/include/tpLinuxTag.h deleted file mode 100644 index 425560a..0000000 --- a/u-boot/include/tpLinuxTag.h +++ /dev/null @@ -1,60 +0,0 @@ - -/************************************************************************************** -* File Name : tpLinuxTag.h -* -* Description: add tag with validation system to the firmware image file to be uploaded -* via http -* -* Created : 16Sep07, Liang Qiming -**************************************************************************************/ - -#ifndef _TP_LINUX_TAG_H_ -#define _TP_LINUX_TAG_H_ - -/* - * File tag (head) structure all is in clear text - * except validationTokens (crc, md5, sha1, etc). - * - * Total: 128 unsigned chars - */ -#define TAG_LEN 512 -#define SIG_LEN 24 -#define SIG_LEN_2 12 // Original second SIG = 20 is now devided into 14 for SIG_LEN_2 and 6 for CHIP_ID -#define CHIP_ID_LEN 8 -#define TOKEN_LEN 20 -#define BOARD_ID_LEN 16 - -/* - * TAG for downloadable image (kernel plus file system) - * integer in the structure is stored in Network-Byte order (BIG-endian) - */ -typedef struct _tplink_image_header_t { - unsigned long tagVersion; - char signiture_1[SIG_LEN]; // text line for company info - char signiture_2[SIG_LEN_2]; // additional info (can be version number) - char chipId[CHIP_ID_LEN]; // chip id - char boardId[BOARD_ID_LEN]; // board id - unsigned long productId; // product id - unsigned long productVer; // product version - unsigned long reserved1; // reserved for future - - unsigned char imageValidationToken[TOKEN_LEN]; // image validation token - md5 checksum - unsigned char kernelValidationToken[TOKEN_LEN]; // kernel+tag validation token - md5 checksum - - unsigned long kernelTextAddr; // text section address of kernel - unsigned long kernelEntryPoint; // entry point address of kernel - - unsigned long totalImageLen; // the sum of kernelLen+rootfsLen+tagLen - - unsigned long kernelAddress; // starting address (offset from the beginning of FILE_TAG) of kernel image - unsigned long kernelLen; // length of kernel image - - unsigned long rootfsAddress; // starting address (offset) of filesystem image - unsigned long rootfsLen; // length of filesystem image - - unsigned long bootloaderAddress; // starting address (offset) of boot loader image - unsigned long bootloaderLen; // length of boot loader image - -} tplink_image_header_t; - -#endif /* ifndef _TP_LINUX_TAG_H_ */ diff --git a/u-boot/include/tplink_image.h b/u-boot/include/tplink_image.h new file mode 100644 index 0000000..2d4e9f0 --- /dev/null +++ b/u-boot/include/tplink_image.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Piotr Dymacz + * + * Based on mktplinkfw.c from OpenWrt + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef __TPLINK_IMAGE_H__ +#define __TPLINK_IMAGE_H__ + +#define TPL_IH_VERSION_V1 0x01000000 +#define TPL_IH_VERSION_V2 0x02000000 +#define TPL_IH_VERSION_V3 0x03000000 + +#define MD5SUM_LEN 16 + +/* For v1 version of header version */ +typedef struct tplink_image_header { /* ofs (size): what */ + uint32_t ih_version; /* 0x0 (4): header version */ + char ih_vendor[24]; /* 0x4 (24): vendor name (text) */ + char ih_info[36]; /* 0x1C (36): other info like version */ + uint32_t ih_hw_id; /* 0x40 (4): hardware ID */ + uint32_t ih_hw_ver; /* 0x44 (4): hardware version */ + uint32_t ih_region; /* 0x48 (4): region code */ + uint8_t ih_md5sum1[MD5SUM_LEN]; /* 0x4C (16): MD5 sum #1 */ + uint32_t ih_ignore1; /* 0x5C (4): unknown */ + uint8_t ih_md5sum2[MD5SUM_LEN]; /* 0x60 (16): MD5 sum #2 */ + uint32_t ih_ignore2; /* 0x70 (4): unknown */ + uint32_t ih_kernel_load; /* 0x74 (4): kernel load address */ + uint32_t ih_kernel_ep; /* 0x78 (4): kernel entry point */ + uint32_t ih_fw_len; /* 0x7C (4): image size (with header) */ + uint32_t ih_kernel_ofs; /* 0x80 (4): kernel data offset */ + uint32_t ih_kernel_len; /* 0x84 (4): kernel data size */ + uint32_t ih_rootfs_ofs; /* 0x88 (4): rootfs data offset */ + uint32_t ih_rootfs_len; /* 0x8C (4): rootfs data size */ + uint32_t ih_boot_ofs; /* 0x90 (4): bootloader data offset */ + uint32_t ih_boot_len; /* 0x94 (4): bootloader data size */ + uint16_t ih_fw_ver_hi; /* 0x98 (2): firmware version hi */ + uint16_t ih_fw_ver_mid; /* 0x9A (2): firmware version mid */ + uint16_t ih_fw_ver_lo; /* 0x9C (2): firmware version lo */ + uint8_t ih_pad[354]; /* 0x9E (354): padding, not used... */ +} tplink_image_header_t; + +#endif /* __TPLINK_IMAGE_H__ */ -- 2.25.1