Hi, all! So, I have the complete solution to make A20 boot from NAND (SPL, U-Boot) + SATA (DTB, Kernel, RootFS). This is to exclude SD-Card from boot process.
First part is a20_nand branch from U-Boot from https://gitlab.com/m.motyl83/u-boot.git <http://U-Boot> NB! a20_nand branch is crucial This will make appropriate SPL (spl/sunxi-spl.bin), which can be loaded to NAND via FEX and will boot. At this moment we have one problem: we have no U-Boot proper prepared for flashing via FEX (u-boot-dtb.bin will be rejected as file with wrong signature). U-Boot does not build U-Boot proper with SUNXI eGON.BT1 signature at all. So I've modified original mksunxi hosttool from U-Boot (source file included). It places correct signature to header of image followed by U-Boot proper code. eGON.BT signatures start from ARM "B" instruction (4 bytes - instruction opcode and address to branch to). Original mksunxi calculates this "branch" instruction (address) to jump over eGON header. For Boot0 it works perfectly (because it is standard offset which is used in any Boot0 image by BROM - be it proprietary Boot0 or U-Boot SPL). But not for Boot1... I don't know where IP (instruction pointer) points to when SPL loads U-Boot proper and tries to "jump" (speaking in terms of x86) to it. So, I didn't know how to calculate address of this instruction. But we know that U-Boot proper code works when SPL jumps right to it (this is proved by inspecting u-boot-sunxi-with-spl.bin and playing with loading images via USB-FEL). Thus I've modified generation of Boot1 image - it places U-Boot proper code with some constant offset (2000h, filled with zeroes). (Also we need to make more space in SUN4I_SRAM_SIZE, because it is Boot1 - it is larger than Boot0). Next step is to modify config. We need to tell SPL to load U-Boot proper from specific offset (avoiding BROM signature and "B" instruction - it will not read it from NAND at all). This lines are: CONFIG_SYS_NAND_U_BOOT_OFFS=0x802000 CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND=0x802000 (These lines are for SPL, so you need to rebuild it to work with U-Boot proper which is generated by modified mksunxi). After all this we can use modified mksunxi (I call it mksunxi-bt1) to build Boot1 image which contains signature, correctly placed U-Boot proper code, can be flashed via FEX and started by SPL (with modified "U-Boot Offs"). -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscr...@googlegroups.com. To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/46bc7592-251c-45de-916c-15b9daab029an%40googlegroups.com.
/* * (C) Copyright 2007-2011 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> * Tom Cubie <tangli...@allwinnertech.com> * * 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 <fcntl.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> typedef unsigned char u8; typedef unsigned int u32; #define ALIGNMENT_SIZE (8192 - 48) #define BOOT1_MAGIC "eGON.BT1" #define STAMP_VALUE 0x5F0A6C39 /* boot head definition from sun4i boot code */ typedef struct boot_file_head { u32 jump_instruction; // one intruction jumping to real code // 4 4 u8 magic[8]; // ="eGON.BT0" or "eGON.BT1", not C-style string. // 8 12 u32 check_sum; // generated by PC // 4 16 u32 length; // generated by PC // 4 20 u32 pub_head_size; // the size of boot_file_head_t // 4 24 u8 pub_head_vsn[4]; // the version of boot_file_head_t // 4 28 u8 file_head_vsn[4]; // the version of boot0_file_head_t or boot1_file_head_t // 4 32 u8 Boot_vsn[4]; // Boot version // 4 36 u8 eGON_vsn[4]; // eGON version // 4 40 u8 platform[8]; // platform information // 8 48 u8 alignment [ALIGNMENT_SIZE]; // to 800h 2048 } boot_file_head_t; /* 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 (1024 * 1024) #define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(boot_file_head_t)) #define BLOCK_SIZE 8192 typedef struct boot_img { boot_file_head_t header; char code[SRAM_LOAD_MAX_SIZE]; char pad[BLOCK_SIZE]; } boot_img_t; int main (int argc, char * argv[]) { int fd_in; int count; int fd_out; unsigned int file_size; unsigned int load_size; boot_img_t img = { .header = { .jump_instruction = 0xDEADBEEF, .magic = BOOT1_MAGIC, .eGON_vsn = "", .Boot_vsn = "", .platform = "", .alignment = { [ 0 ... (ALIGNMENT_SIZE - 1) ] = -1 }, }, .code = { 0 }, .pad = { 0 } }; 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 (bytes):\t%xh/%d\n", file_size, 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 (bytes):\t%xh/%d\n", load_size, 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 (bytes):\t\t%xh/%d\n", count, count); /* fill the header */ 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 (bytes):\t\t%xh/%d\n", count, count); close (fd_in); close (fd_out); return EXIT_SUCCESS; }