#  ----------------------------------------------------------------------------
#          ATMEL Microcontroller Software Support  -  ROUSSET  -
#  ----------------------------------------------------------------------------
#  Copyright (c) 2006, Atmel Corporation
#
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#
#  - Redistributions of source code must retain the above copyright notice,
#  this list of conditions and the disclaiimer below.
#
#  - Redistributions in binary form must reproduce the above copyright notice,
#  this list of conditions and the disclaimer below in the documentation and/or
#  other materials provided with the distribution. 
#
#  Atmel's name may not be used to endorse or promote products derived from
#  this software without specific prior written permission. 
#
#  DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
#  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
#  DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
#  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
#  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#  ----------------------------------------------------------------------------


################################################################################
#  proc uboot_env: Convert u-boot variables in a string ready to be flashed
#                  in the region reserved for environment variables
################################################################################
proc set_uboot_env {nameOfLstOfVar} {
    upvar $nameOfLstOfVar lstOfVar
    
    # sector size is the size defined in u-boot CFG_ENV_SIZE
    set sectorSize [expr 0x20000 - 4]

    set strEnv [join $lstOfVar "\0"]
    while {[string length $strEnv] < $sectorSize} {
        append strEnv "\0"
    }
    set strCrc [binary format i [::vfs::crc $strEnv]]
    return "$strCrc$strEnv"
}


################################################################################
#  Sanity Checks:
#               Checks the mapping regarding the kernel and the disk size
################################################################################
proc is_mapping_correct {} {
    variable nf_mapping
    variable bootstrapSize
    variable ubootSize
    variable kernelSize
    variable diskSize
    
    # ### Check the offset in NAND ###
    # Check if there is enough space for the bootstrap before uboot
    if {[expr ($nf_mapping(bootstrapOff) + $bootstrapSize)] > $nf_mapping(ubootOff)} {
        error "-F- The area for the bootstrap in NAND is not large enough $nf_mapping(bootstrapSize)"
    }
    # Check if there is enough space for the uboot before uboot environment variables
     if {[expr ($nf_mapping(ubootOff) + $ubootSize)] > $nf_mapping(ubootEnvOff)} {
         error "-F- The area for the uboot in NAND is not large enough $ubootSize"
    }
    # Check if there is enough space for the kernel before the ramdisk
    if {[expr ($nf_mapping(kernelOff) + $kernelSize)] > $nf_mapping(diskOff)} {
        error "-F- The area for the kernel in NAND is not large enough $nf_mapping(kernelSize)"
    }
   
    # ### Check the position in sdram ###
    if {[expr ($nf_mapping(diskSdram) + $diskSize)] > $nf_mapping(kernelSdram)} {
        error "-F- The area for the disk in SDRAM is not large enough $nf_mapping(diskSize)"
    }
}

################################################################################
#  Main script: Load the linux demo in NAND flash,
#               Update the environment variables
################################################################################


array set nf_mapping {
    bootstrapFileName   "GESBC-9260S.bin"
    kernelFileName      "uImage"
    diskFileName        "rootfs-emdebian.img"
    ubootEnvFileName    "tmp.bin"
    
    bootstrapOff    0x00000000
    ubootOff        0x00020000
    ubootEnvOff     0x00060000
    kernelOff       0x00100000
    diskOff         0x00400000
    
    kernelSdram     0x21800000
    diskSdram       0x20800000
}

set binPath [lindex $::argv 3]
set ubootFileName [lindex $::argv 4]
puts "u-boot file: $ubootFileName"

set bootstrapFile [file join $binPath $nf_mapping(bootstrapFileName)]
set ubootFile [file join $binPath $ubootFileName]
set kernelFile [file join $binPath $nf_mapping(kernelFileName)]
set diskFile [file join $binPath $nf_mapping(diskFileName)]

set bootstrapSize [format "0x%08X" [file size $nf_mapping(bootstrapFileName)]]
set ubootSize     [format "0x%08X" [file size $ubootFileName]]
set kernelSize    [format "0x%08X" [file size $nf_mapping(kernelFileName)]]
set diskSize      [format "0x%08X" [file size $nf_mapping(diskFileName)]]
puts "diskSize: $diskSize"

puts "-I- === Performs sanity checks=== "
if { [catch {is_mapping_correct} eid] } {
    puts "$eid"
    exit 1
}

catch {is_mapping_correct} 

lappend u_boot_variables \
    "ethaddr=3a:1f:34:08:54:54" \
    "bootdelay=3" \
    "baudrate=115200" \
    "stdin=serial" \
    "stdout=serial" \
    "stderr=serial" \
    "bootargs=mem=64M console=ttyS0,115200 root=/dev/mtdblock2 rw rootfstype=jffs2 mtdparts=at91_nand:1M(bootloader),3M(kernel),-(rootfs)" \
    "bootcmd=\
nand read $nf_mapping(kernelSdram) $nf_mapping(kernelOff) $kernelSize;\
nand read $nf_mapping(diskSdram) $nf_mapping(diskOff) $diskSize;\
bootm $nf_mapping(kernelSdram)"

#puts "-I- === Initialize the DataFlash access ==="
#DATAFLASH::SelectDataflash AT91C_SPI0_CS1

#puts "-I- === Erase all the DataFlash blocs and test the erasing ==="
#DATAFLASH::EraseAllDataFlash


puts "-I- === Initialize the NAND access ==="
NANDFLASH::Init

puts "-I- === Erase all the NAND flash blocs and test the erasing ==="
NANDFLASH::EraseAllNandFlash

puts "-I- === Load the bootstrap: nandflash_at91sam9260ek in the first sector ==="
send_file {NandFlash} "$bootstrapFile" $nf_mapping(bootstrapOff) 0

puts "-I- === Load the u-boot in the next sectors ==="
send_file {NandFlash} "$ubootFile" $nf_mapping(ubootOff) 0 

puts "-I- === Load the u-boot environment variables ==="
set fh [open "$nf_mapping(ubootEnvFileName)" w]
fconfigure $fh -translation binary
puts -nonewline $fh [set_uboot_env u_boot_variables]
close $fh
send_file {NandFlash} "$nf_mapping(ubootEnvFileName)" $nf_mapping(ubootEnvOff) 0 

puts "-I- === Load the Kernel image ==="
send_file {NandFlash} "$nf_mapping(kernelFileName)" $nf_mapping(kernelOff) 0

puts "-I- === Load the linux file system ==="
send_file {NandFlash} "$nf_mapping(diskFileName)" $nf_mapping(diskOff) 0



