/* * (C) Copyright 2007-2011 * Allwinner Technology Co., Ltd. * Tom Cubie * * Boot an image which is generated by android mkbootimg tool * * (C) Copyright 2000-2003 * 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 */ /* * Misc boot support */ #include #include #include #include #ifdef CONFIG_CMD_BOOTA #include #ifdef CONFIG_SUNXI_SECURE_SYSTEM #include #endif int __do_sunxi_boot_signature(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { return 0; } int do_sunxi_boot_signature(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) __attribute__((weak, alias("__do_sunxi_boot_signature"))); static unsigned char boot_hdr[512]; extern int do_boota_linux (struct fastboot_boot_img_hdr *hdr); DECLARE_GLOBAL_DATA_PTR; void * memcpy2(void * dest,const void * src,__kernel_size_t n) { if (src == dest) return dest; if (src < dest) { if (src + n > dest) { memcpy((void*) (dest + (dest - src)), dest, src + n - dest); n = dest - src; } memcpy(dest, src, n); } else { memcpy(dest, src, n); } return dest; } int do_boota (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr; unsigned kaddr, raddr; #ifdef CONFIG_SUNXI_SECURE_SYSTEM char efuse_hash[32] , all_zero[32]; int ret; #endif if (argc < 2) return cmd_usage(cmdtp); addr = simple_strtoul(argv[1], NULL, 16); struct fastboot_boot_img_hdr *fb_hdr = (struct fastboot_boot_img_hdr *)addr; image_header_t *hdr =(image_header_t *)(addr + CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE); /* save the image header somewhere */ memcpy(boot_hdr, (void*) addr, sizeof(*hdr)); if (memcmp(fb_hdr->magic, FASTBOOT_BOOT_MAGIC, 8)) { puts("boota: bad boot image magic, maybe not a boot.img?\n"); return 1; } #ifdef DEBUG printf("---------------------\n"); printf("kernel size: 0x%x \n", fb_hdr->kernel_size); printf("kernel addr: 0x%x \n", fb_hdr->kernel_addr); printf("ramdisk size: 0x%x \n", fb_hdr->ramdisk_size); printf("ramdisk addr: 0x%x \n", fb_hdr->ramdisk_addr); printf("second size: 0x%x \n", fb_hdr->second_size); printf("second addr: 0x%x \n", fb_hdr->second_addr); printf("name: %s\n", fb_hdr->name); printf("cmdline: %s\n", fb_hdr->cmdline); #endif kaddr = addr + fb_hdr->page_size; raddr = kaddr + ALIGN(fb_hdr->kernel_size, fb_hdr->page_size); #ifdef DEBUG printf("moving kernel from %x to: %x, size 0x%x\n", kaddr, fb_hdr->kernel_addr, fb_hdr->kernel_size); printf("moving ramdisk from %x to: %x, size 0x%x\n", raddr, fb_hdr->ramdisk_addr, fb_hdr->ramdisk_size); #endif //memmove((void*) fb_hdr->kernel_addr, (const void *)kaddr, fb_hdr->kernel_size); //memmove((void*) fb_hdr->ramdisk_addr, (const void *)raddr, fb_hdr->ramdisk_size); memcpy2((void*) fb_hdr->kernel_addr, (const void *)kaddr, fb_hdr->kernel_size); memcpy2((void*) fb_hdr->ramdisk_addr, (const void *)raddr, fb_hdr->ramdisk_size); /* add code for signature */ #ifdef CONFIG_SUNXI_SECURE_SYSTEM if(gd->securemode) { unsigned int total_len = raddr + ALIGN(fb_hdr->ramdisk_size, fb_hdr->page_size) - addr; printf("total_len=%d\n", total_len); //为了签名检查,必须知道当前启动的分区名称 ret = sunxi_verify_signature((void *)addr, total_len, argv[2]); setenv("verifiedbootstate", "green"); if(ret) { printf("boota: verify the %s failed\n", argv[2]); setenv("verifiedbootstate", "red"); printf("start to display warnings.bmp\n"); sunxi_bmp_display("warnings.bmp"); } memset(efuse_hash, 0, 32); ret = sunxi_efuse_read("rotpk", efuse_hash); if(ret) { printf("read efuse rotpk failed\n"); } else { printf("read efuse rotpk successed\n"); sunxi_dump(efuse_hash, 32); } memset(all_zero, 0, 32); if(memcmp(all_zero, efuse_hash,32 ) ){ printf("rotpk has been burn to efuse\n"); setenv("sunxi_rotpk", "true"); } else{ printf("rotpk efuse is empty\n"); setenv("sunxi_rotpk", "flase"); } } #else do_sunxi_boot_signature(NULL, 0, 0, NULL); #endif tick_printf("ready to boot\n"); do_boota_linux(fb_hdr); puts("Boot linux failed, control return to monitor\n"); return 0; } U_BOOT_CMD( boota, 3, 1, do_boota, "boota - boot android bootimg from memory\n", "\n - boot application image stored in memory\n" "\t'addr' should be the address of boot image which is kernel+ramdisk.img\n" ); #endif