# -*- mode: python; coding: utf-8; -*-

#  Codezero -- a microkernel for embedded systems.
#
#  Copyright © 2009  B Labs Ltd
#
#  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: Russel Winder

import os.path
import subprocess
import shutil

Import('environment', 'images')

e = environment.Clone()
e.Append(LINKFLAGS = ['-T' + e['posixServicesDirectory'] + '/bootdesc/linker.lds'])
e.Append(CPPPATH = ['#' + e['includeDirectory']])

bootdescTemplate = \
'''
/* This file is autogenerated, do not edit by hand. */

/* Supervisor task at load time. */
struct svc_image {
        char name[16];
        unsigned int phys_start;
        unsigned int phys_end;
} __attribute__((__packed__));

/* Supervisor task descriptor at load time */
struct bootdesc {
        int desc_size;
        int total_images;
        struct svc_image images[];
} __attribute__((__packed__));

struct bootdesc bootdesc = {
        .desc_size = sizeof(struct bootdesc) + sizeof(struct svc_image) * %s,
        .total_images = %s,
        .images = {
%s
        },
};
'''

imageTemplate = \
'''             [%s] = {
                        .name = "%s",
                        .phys_start = %s,
                        .phys_end = %s,
                },
'''

def generateLocationData(image):
    process = subprocess.Popen('tools/pyelf/readelf.py --lma-start-end ' + image.path, shell=True, stdout=subprocess.PIPE)
    assert process.wait() == 0
    return (process.stdout.readline().strip(), process.stdout.readline().strip().split()[1], process.stdout.readline().strip().split()[1])

def generateBootdesc(target, source, env):
    '''
    Extracts name, start, end information from the kernel and each svc task.
    Uses this information to produce bootdesc.c
    '''
    with open(target[0].path, 'w' ) as f:
        imagesString = ''
        numberOfImages = len(source) - 1
        for index in range(1, len(source)):
            imagesString += imageTemplate % ((index - 1,) + generateLocationData(source[index]))
        f.write(bootdescTemplate % (numberOfImages, numberOfImages, imagesString))

def relocateBootdesc(target, source, env):
    name, start, end = generateLocationData(source[1])
    print "arm-none-linux-gnueabi-objcopy" + " --adjust-section-vma .data=" + end + " " + source[0].path
#    process = subprocess.Popen(executable='arm-none-linux-gnueabi-objcopy', args=(
#           '--adjust-section-vma .data=' + end,
#            source[0].path))
#    assert process.wait() == 0
    os.system("arm-none-linux-gnueabi-objcopy --adjust-section-vma .data=" + end + " " + source[0].path)
    shutil.copyfile(source[0].path, target[0].path)

objects = e.Object(e.Command('bootdesc.c', images, generateBootdesc))
Depends(objects, e['configFiles'])
bootdesc = e.Command('bootdesc.axf', e.Program('bootdesc_intermediate', objects) + [images[1]] , relocateBootdesc)
Depends(bootdesc, e['configFiles'])

Return('bootdesc')
