#!/usr/bin/env python2 # -*- 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 . __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 sys, getopt inputfile = '' outputfile = '' argv = sys.argv[1:] try: opts, args = getopt.getopt(argv,"hu:o:",["uboot=","outfile="]) except getopt.GetoptError: print 'test.py -u -o ' sys.exit(2) if len(argv) == 0: print 'test.py -u -o ' sys.exit() for opt, arg in opts: if opt == '-h': print 'test.py -u -o ' sys.exit() elif opt in ("-u", "--uboot"): inputfile = arg elif opt in ("-o", "--outfile"): outputfile = arg print 'Input file is:', inputfile print 'Output file is:', outputfile exit 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 (inputfile): try: uboot_image_len=os.path.getsize(inputfile) print 'Using %s to get image length - it is %i (0x%x) bytes'%(os.path.abspath(inputfile),uboot_image_len,uboot_image_len) except: print 'Specified u-boot.bin file: %s (%s) not found'%(inputfile,os.path.abspath(inputfile)) sys.exit() 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 outputfile: print 'Generating binary output ',os.path.abspath(outputfile) bf=open(outputfile,'wb') data=struct.pack('I' * len(image), *image) bf.write(data) spl=open(inputfile,'rb') bf.write(spl.read()) bf.close() spl.close()