]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
zynq: Generate boot.bin automatically
authorMichal Simek <michal.simek@xilinx.com>
Mon, 20 Jan 2014 15:06:35 +0000 (16:06 +0100)
committerMichal Simek <michal.simek@xilinx.com>
Fri, 31 Jan 2014 08:35:22 +0000 (09:35 +0100)
Do not spend any time on boot.bin generation.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Makefile
tools/zynq-boot-bin.py [new file with mode: 0755]

index 47a03e34e739327f6218083fd8b3d5094359b97d..d89962d03f858ada5d305eade79f9eb186c93edd 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -362,6 +362,10 @@ endif
 endif
 endif
 
+ifneq ($(CONFIG_ZYNQ),)
+ALL-y += $(obj)boot.bin
+endif
+
 build := -f $(TOPDIR)/scripts/Makefile.build -C
 
 all:           $(ALL-y) $(SUBDIR_EXAMPLES-y)
@@ -506,6 +510,9 @@ endif
 $(obj)u-boot-img.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.img
                cat $(obj)spl/u-boot-spl.bin $(obj)u-boot.img > $@
 
+$(obj)boot.bin: $(obj)spl/u-boot-spl.bin
+       tools/zynq-boot-bin.py -o $(obj)boot.bin -u $(obj)spl/u-boot-spl.bin
+
 # PPC4xx needs the SPL at the end of the image, since the reset vector
 # is located at 0xfffffffc. So we can't use the "u-boot-img.bin" target
 # and need to introduce a new build target with the full blown U-Boot
diff --git a/tools/zynq-boot-bin.py b/tools/zynq-boot-bin.py
new file mode 100755 (executable)
index 0000000..a5c11ca
--- /dev/null
@@ -0,0 +1,210 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2014, Xilinx.inc.
+#
+# Hack origin version and just take the part which generate boot.bin
+# for U-BOOT SPL.
+#
+# Copyright (C) 2013, Elphel.inc.
+# pre-u-boot configuration of the Xilinx Zynq(R) SoC
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+
+__author__ = "Andrey Filippov"
+__copyright__ = "Copyright 2013, Elphel, Inc."
+__license__ = "GPL"
+__version__ = "3.0+"
+__maintainer__ = "Andrey Filippov"
+__email__ = "andrey@elphel.com"
+__status__ = "Development"
+import os
+import struct
+import argparse # http://docs.python.org/2/howto/argparse.html
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-o', '--outfile',   help='Path to save the generated boot file')
+parser.add_argument('-u', '--uboot',      help='path to the u-boot.bin to get it\'s length (second pass, when u-boot.bin is already generated)')
+
+args = parser.parse_args()
+#print args
+
+ACCESSIBLE_REGISTERS=((0xe0001000,0xe0001fff), # UART1 controller registers
+                      (0xe000d000,0xe000efff), # QUAD SPI controller registers
+                      (0xe0100004,0xe0100057), # SDIO 0 controller registers
+                      (0xe0100059,0xe0100fff), # SDIO 0 controller registers
+                      (0xe000e000,0xe000efff), # SMC controller
+                      (0xf8006000,0xf8006fff), # DDR controller
+                      # SLCR_LOCK disables all (0xf8000000,0xf8000b74), but it is locked at reset seems to be unlocked, http://www.xilinx.com/support/answers/47570.html
+                      #prohibited: SLCR_SCL, SLCR_LOCK, SLCR_UNLOCK, SLCR_STA
+                      (0xf8000100,0xf80001b0), # SLCR registers
+                      #DOes not seem to be any gap between 0xf80001b0 and 0xf80001b4
+                      (0xf80001b4,0xf80001ff), # SLCR registers
+                      #prohibited SLCR_PSS_RST_CTRL 0xf8000200
+                      (0xf8000204,0xf8000234), # SLCR registers - is  SLCR_SMC_RST_CTRL 0xf8000234 also prohibited?
+                      #prohibited? SLCR_OCM_RST_CTRL 0xf8000238 SLCR_FPGA_RST_CTRL 0xf8000240
+                      (0xf800024c,0xf800024c), # SLCR registers SLCR_AWDT_CTRL - watchdog timer reset control
+                      #prohibited SLSR_REBOOT_STATUS 0xf8000258, SLCR_BOOT_MODE 0xf800025c, SLCR_APU_CTRL 0xf8000300,
+                      (0xf8000304,0xf8000834), # SLCR registers SLCR_AWDT_CLK_SEL,  DDR, MIO
+                      #prohibited SLCR_LVL_SHFTR_ON 0xf8000900, SLCR_OCM_CFG 0xf8000910,
+                      (0xf8000a00,0xf8000a8c), # SLCR registers All shown "reserved" ???
+                      (0xf8000ab0,0xf8000b74)) # SLCR registers iostd, voltages,  - more DDR stuff
+
+def verify_register_accessible(address):
+    for interval in ACCESSIBLE_REGISTERS:
+        if (address >= interval[0]) and (address <= interval[1]):
+            print 'Register accessible:' , hex(interval[0]),'<=', hex(address), '<=', hex(interval[1])
+            return True
+    else:
+        return False
+
+def image_generator (image,
+                       reg_sets, # registers,
+                       options,
+                       user_def,
+                       ocm_offset,
+                       ocm_len,
+                       start_exec):
+    reserved0044=0;
+
+    rfi_word=0xeafffffe #from actual image
+    waddr=0
+    for _ in range (0x20/4):
+        image[waddr]=rfi_word # fill reserved for interrupts fields
+        waddr+=1
+    #width detection
+    image[waddr]=0xaa995566 # offset 0x20
+    waddr+=1
+
+    #image identification
+    image[waddr]=0x584c4e58 # offset 0x24, XLNX
+    waddr+=1
+
+    #encryption status
+    image[waddr]=0x0 # offset 0x28, no encryption
+    waddr+=1
+
+    #User defined word
+    image[waddr]=user_def # offset 0x2c
+    waddr+=1
+
+    #ocm_offset
+    if ocm_offset<0x8c0:
+        print 'Start offset should be >= 0x8c0, specified', hex(ocm_offset)
+        exit (ERROR_DEFS['HEAD'])
+    elif (ocm_offset & 0x3f) != 0:
+        print 'Start offset should be 64-bytes aligned, specified', hex(ocm_offset)
+        exit (ERROR_DEFS['HEAD'])
+    image[waddr]=ocm_offset # offset 0x30
+    waddr+=1
+
+    #ocm_len
+    if ocm_len>0x30000:
+        print 'Loaded to the OCM image should fit into 3 mapped pages of OCM - 192K (0x30000), specified ',hex(ocm_len)
+        exit (ERROR_DEFS['HEAD'])
+    image[waddr]=ocm_len # offset 0x34
+    waddr+=1
+
+    #reserved 0
+    image[waddr]=0 # offset 0x38
+    waddr+=1
+
+    #start_exec
+    if (start_exec>0x30000) or (start_exec<0):
+        print 'Start address is relative to  OCM and should fit there - in 192K (0x30000), specified ',hex(start_exec)
+        exit (ERROR_DEFS['HEAD'])
+    image[waddr]=start_exec # offset 0x3c
+    waddr+=1
+
+    #img_len == ocm_len for unsecure images
+    img_len = ocm_len
+    image[waddr]=img_len # offset 0x40
+    waddr+=1
+
+    #reserved 0
+    image[waddr]=reserved0044 #0  # offset 0x44
+    waddr+=1
+
+    #calculate image checksum
+    def add (x,y): return x+y
+    checksum=(reduce(add,image[0x20/4:0x48/4]) ^ 0xffffffff) & 0xffffffff
+    image[waddr]=checksum # offset 0x48
+    waddr+=1
+    print 'After checksum waddr=',hex(waddr),' byte addr=',hex(4*waddr)
+
+
+    #initialize registers
+    print 'Number of registers to initialize',len(reg_sets)
+    if len (reg_sets)>256:
+        print 'Too many registers to initialize, only 256 allowed,',len(reg_sets),'> 256'
+    waddr=0xa0/4
+    # new_sets.append((addr,data,mask,self.module_name,register_name,self.defs[register_name]))
+
+    for register in reg_sets:
+        op=register[0]
+        addr=register[1]
+        data=register[2]
+        if (op != 's'):
+            raise Exception ('Can not test registers (0x%08x) in RBL, it should be done in user code'%addr)
+        if not verify_register_accessible (addr):
+            print 'Tried to set non-accessible register', hex(addr),' with data ', hex(data)
+            exit (ERROR_DEFS['NONACCESSIBLE_REGISTER'])
+        image[waddr]=addr
+        waddr+=1
+        image[waddr]=data
+        waddr+=1
+    #Fill in FFs for unused registers
+    while waddr < (0x8c0/4):
+        image[waddr]=0xffffffff
+        waddr+=1
+        image[waddr]=0
+        waddr+=1
+
+if (args.uboot):
+    try:
+        uboot_image_len=os.path.getsize(args.uboot)
+        print 'Using %s to get image length - it is %i (0x%x) bytes'%(os.path.abspath(args.uboot),uboot_image_len,uboot_image_len)
+    except:
+        print 'Specified u-boot.bin file: %s (%s) not found'%(args.uboot,os.path.abspath(args.uboot))
+else:
+    uboot_image_len=int(raw_options['CONFIG_EZYNQ_BOOT_OCM_IMAGE_LENGTH'],0)
+    print 'No u-boot.bin path specified, using provided CONFIG_EZYNQ_BOOT_OCM_IMAGE_LENGTH as image size of %i (0x%x) bytes for the RBL header'%(uboot_image_len,uboot_image_len)
+
+image =[ 0 for k in range (0x8c0/4)]
+reg_sets=[]
+num_rbl_regs=0
+
+raw_configs=""
+raw_options={}
+
+
+image_generator (image,
+                 reg_sets[:num_rbl_regs], #
+                 #registers,
+                 raw_options,
+                 0x1010000, # user_def
+                 0x8c0, # ocm_offset,
+                 uboot_image_len, #ocm_len,
+                 0) #start_exec)
+
+if args.outfile:
+    print 'Generating binary output ',os.path.abspath(args.outfile)
+    bf=open(args.outfile,'wb')
+    data=struct.pack('I' * len(image), *image)
+    bf.write(data)
+
+    spl=open(args.uboot,'rb')
+    bf.write(spl.read())
+
+    bf.close()
+    spl.close()