From patchwork Sun Nov 25 11:40:50 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Henrik_Nordstr=C3=B6m?= X-Patchwork-Id: 201523 X-Patchwork-Delegate: albert.aribaud@free.fr Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id A3B9E2C007E for ; Sun, 25 Nov 2012 22:41:06 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4E0174A039; Sun, 25 Nov 2012 12:41:04 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id uGECHzG35Lqt; Sun, 25 Nov 2012 12:41:03 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BEA274A03A; Sun, 25 Nov 2012 12:41:01 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C8AAA4A03A for ; Sun, 25 Nov 2012 12:40:59 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Pw1NdzJxbF8y for ; Sun, 25 Nov 2012 12:40:58 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from vps1.hno.se (vps1.hno.se [31.192.227.87]) by theia.denx.de (Postfix) with ESMTPS id D36914A039 for ; Sun, 25 Nov 2012 12:40:56 +0100 (CET) Received: from home.hno.se (home.hno.se [IPv6:2001:470:df90::1]) (authenticated bits=128) by vps1.hno.se (8.14.4/8.14.4) with ESMTP id qAPBeqC8014207 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 25 Nov 2012 12:40:53 +0100 Received: from [127.0.0.1] (localhost.localdomain [127.0.0.1]) by home.hno.se (8.14.5/8.14.5) with ESMTP id qAPBeoYe015444 for ; Sun, 25 Nov 2012 12:40:51 +0100 Message-ID: <1353843650.17518.18.camel@home.hno.se> From: Henrik =?ISO-8859-1?Q?Nordstr=F6m?= To: U-Boot Mailing List Date: Sun, 25 Nov 2012 12:40:50 +0100 In-Reply-To: References: X-Mailer: Evolution 3.2.3 (3.2.3-3.fc16) Mime-Version: 1.0 Subject: [U-Boot] [PATCH 07/22] tools: mksunixboot adding a Allwinner boot header X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de This tool adds a boot header to the supplied file, for booting code directly from the SoC embedded boot rom. Needed for making the SPL loader bootable. From: Tom Cubie Signed-off-by: Henrik Nordstrom Signed-off-by: Stefan Roese --- Makefile | 1 + tools/.gitignore | 1 + tools/Makefile | 6 ++ tools/mksunxiboot.README | 13 ++++ tools/mksunxiboot.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+), 0 deletions(-) create mode 100644 tools/mksunxiboot.README create mode 100644 tools/mksunxiboot.c diff --git a/Makefile b/Makefile index 5a98745..81fe532 100644 --- a/Makefile +++ b/Makefile @@ -799,6 +799,7 @@ clean: $(obj)tools/gen_eth_addr $(obj)tools/img2srec \ $(obj)tools/mk{env,}image $(obj)tools/mpc86x_clk \ $(obj)tools/mk{smdk5250,}spl \ + $(obj)tools/mksunxiboot \ $(obj)tools/mxsboot \ $(obj)tools/ncb $(obj)tools/ubsha1 \ $(obj)tools/kernel-doc/docproc diff --git a/tools/.gitignore b/tools/.gitignore index 9bce719..92fcbbd 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -7,6 +7,7 @@ /mkimage /mpc86x_clk /mxsboot +/mksunxiboot /ncb /ncp /ubsha1 diff --git a/tools/Makefile b/tools/Makefile index 686840a..508112d 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -69,6 +69,7 @@ BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) BIN_FILES-y += mkenvimage$(SFX) BIN_FILES-y += mkimage$(SFX) BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX) +BIN_FILES-$(CONFIG_SUNXI) += mksunxiboot$(SFX) BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX) BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX) @@ -98,6 +99,7 @@ NOPED_OBJ_FILES-y += omapimage.o NOPED_OBJ_FILES-y += mkenvimage.o NOPED_OBJ_FILES-y += mkimage.o OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o +OBJ_FILES-$(CONFIG_SUNXI) += mksunxiboot.o OBJ_FILES-$(CONFIG_MX28) += mxsboot.o OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o NOPED_OBJ_FILES-y += os_support.o @@ -228,6 +230,10 @@ $(obj)mpc86x_clk$(SFX): $(obj)mpc86x_clk.o $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@ +$(obj)mksunxiboot$(SFX): $(obj)mksunxiboot.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + $(obj)mxsboot$(SFX): $(obj)mxsboot.o $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@ diff --git a/tools/mksunxiboot.README b/tools/mksunxiboot.README new file mode 100644 index 0000000..9a4b379 --- /dev/null +++ b/tools/mksunxiboot.README @@ -0,0 +1,13 @@ +This program make a arm binary file can be loaded by Allwinner A10 and releated +chips from storage media such as nand and mmc. + +More information about A10 boot, please refer to +http://rhombus-tech.net/allwinner_a10/a10_boot_process/ + +To compile this program, just type make, you will get 'mksunxiboot'. + +To use it, +$./mksunxiboot u-boot.bin u-boot-mmc.bin +then you can write it to a mmc card with dd. +$sudo dd if=u-boot-mmc.bin of=/dev/sdb bs=1024 seek=8 +then insert your mmc card to your A10 tablet, you can boot from mmc card. diff --git a/tools/mksunxiboot.c b/tools/mksunxiboot.c new file mode 100644 index 0000000..fd81529 --- /dev/null +++ b/tools/mksunxiboot.c @@ -0,0 +1,162 @@ +/* + * (C) Copyright 2007-2011 + * Allwinner Technology Co., Ltd. + * Tom Cubie + * + * a simple tool to generate bootable image for sunxi platform. + * + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned char u8; +typedef unsigned int u32; + +/* boot head definition from sun4i boot code */ +typedef struct boot_file_head { + u32 jump_instruction; /* one intruction jumping to real code */ + u8 magic[8]; /* ="eGON.BT0" or "eGON.BT1", not C-style str */ + u32 check_sum; /* generated by PC */ + u32 length; /* generated by PC */ +#if 1 + /* We use a simplified header, only filling in what is needed by the + * boot ROM. To be compatible with Allwinner tools the larger header + * below should be used, followed by a custom header if desired. */ + u8 pad[12]; /* align to 32 bytes */ +#else + u32 pub_head_size; /* the size of boot_file_head_t */ + u8 pub_head_vsn[4]; /* the version of boot_file_head_t */ + u8 file_head_vsn[4]; /* the version of boot0_file_head_t or + boot1_file_head_t */ + u8 Boot_vsn[4]; /* Boot version */ + u8 eGON_vsn[4]; /* eGON version */ + u8 platform[8]; /* platform information */ +#endif +} boot_file_head_t; + +#define BOOT0_MAGIC "eGON.BT0" +#define STAMP_VALUE 0x5F0A6C39 + +/* check sum functon from sun4i boot code */ +int gen_check_sum(void *boot_buf) +{ + boot_file_head_t *head_p; + u32 length; + u32 *buf; + u32 loop; + u32 i; + u32 sum; + + head_p = (boot_file_head_t *) boot_buf; + length = head_p->length; + if ((length & 0x3) != 0) /* must 4-byte-aligned */ + return -1; + buf = (u32 *) boot_buf; + head_p->check_sum = STAMP_VALUE; /* fill stamp */ + loop = length >> 2; + + /* calculate the sum */ + for (i = 0, sum = 0; i < loop; i++) + sum += buf[i]; + + /* write back check sum */ + head_p->check_sum = sum; + + return 0; +} + +#define ALIGN(x, a) __ALIGN_MASK((x), (typeof(x))(a)-1) +#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) + +#define SUN4I_SRAM_SIZE (24 * 1024) +#define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(boot_file_head_t)) +#define BLOCK_SIZE 512 + +struct boot_img { + boot_file_head_t header; + char code[SRAM_LOAD_MAX_SIZE]; + char pad[BLOCK_SIZE]; +}; + +int main(int argc, char *argv[]) +{ + int fd_in, fd_out; + struct boot_img img; + unsigned file_size, load_size; + int count; + + if (argc < 2) { + printf + ("\tThis program makes an input bin file to sun4i bootable image.\n" + "\tUsage: %s input_file out_putfile\n", argv[0]); + return EXIT_FAILURE; + } + + fd_in = open(argv[1], O_RDONLY); + if (fd_in < 0) { + perror("Open input file:"); + return EXIT_FAILURE; + } + + fd_out = open(argv[2], O_WRONLY | O_CREAT, 0666); + if (fd_out < 0) { + perror("Open output file:"); + return EXIT_FAILURE; + } + + memset((void *)img.pad, 0, BLOCK_SIZE); + + /* get input file size */ + file_size = lseek(fd_in, 0, SEEK_END); + printf("File size: 0x%x\n", file_size); + + if (file_size > SRAM_LOAD_MAX_SIZE) + load_size = SRAM_LOAD_MAX_SIZE; + else + load_size = ALIGN(file_size, sizeof(int)); + printf("Load size: 0x%x\n", load_size); + + /* read file to buffer to calculate checksum */ + lseek(fd_in, 0, SEEK_SET); + count = read(fd_in, img.code, load_size); + printf("Read 0x%x bytes\n", count); + + /* fill the header */ + img.header.jump_instruction = /* b instruction */ + 0xEA000000 | /* jump to the first instr after the header */ + ((sizeof(boot_file_head_t) / sizeof(int) - 2) + & 0x00FFFFFF); + memcpy(img.header.magic, BOOT0_MAGIC, 8); /* no '0' termination */ + img.header.length = + ALIGN(load_size + sizeof(boot_file_head_t), BLOCK_SIZE); + gen_check_sum((void *)&img); + + count = write(fd_out, (void *)&img, img.header.length); + printf("Write 0x%x bytes\n", count); + + close(fd_in); + close(fd_out); + + return EXIT_SUCCESS; +}