diff --git a/config/projpaths.py b/config/projpaths.py index 7e9192f..d36faee 100644 --- a/config/projpaths.py +++ b/config/projpaths.py @@ -26,9 +26,14 @@ LINUXDIR = join(PROJROOT, 'conts/linux') LINUX_KERNELDIR = join(LINUXDIR, 'linux-2.6.28.10') LINUX_ROOTFSDIR = join(LINUXDIR, 'rootfs') +POSIXDIR = join(PROJROOT, 'conts/posix') +POSIX_BOOTDESCDIR = join(POSIXDIR, 'bootdesc') + projpaths = { \ 'LINUX_ROOTFSDIR' : LINUX_ROOTFSDIR, \ 'LINUX_KERNELDIR' : LINUX_KERNELDIR, \ 'LINUXDIR' : LINUXDIR, \ 'BUILDDIR' : BUILDDIR, \ + 'POSIXDIR' : POSIXDIR, \ + 'POSIX_BOOTDESCDIR' : POSIX_BOOTDESCDIR } diff --git a/conts/posix/SConstruct b/conts/posix/SConstruct index 5fb264b..0320032 100644 --- a/conts/posix/SConstruct +++ b/conts/posix/SConstruct @@ -76,18 +76,27 @@ fs0 = SConscript('fs0/SConscript', \ test0_env = env.Clone() test0_env.Replace(CPPPATH = ['include', KERNEL_INCLUDE, LIBL4_INCLUDE, LIBMEM_INCLUDE]) -#test0_env.Replace(CPPPATH = [LIBPOSIX_INCLUDE_USERSPACE, 'include', LIBC_INCLUDE, KERNEL_INCLUDE, LIBL4_INCLUDE, LIBMEM_INCLUDE]) -#test0_env.Append(CCFLAGS = '-nostdinc') test0 = SConscript('test0/SConscript', \ exports = { 'config' : config, 'environment' : test0_env, 'contid' : contid}, duplicate = 0, \ variant_dir = join(BUILDDIR, 'cont' + str(contid) + '/posix' + '/test0')) +images = [mm0, fs0, test0] +bootdesc_env = env.Clone() +bootdesc_env['bootdesc_dir'] = 'bootdesc' + +bootdesc = SConscript('bootdesc/SConscript', \ + exports = { 'config' : config, 'environment' : bootdesc_env, \ + 'contid' : contid, 'images' : images }, duplicate = 0, \ + variant_dir = join(BUILDDIR, 'cont' + str(contid) + '/posix' + '/bootdesc')) + Depends(fs0, libposix) Depends(test0, libposix) +Depends(bootdesc, [fs0, test0, mm0]) Alias('libposix', libposix) Alias('mm0', mm0) Alias('fs0', fs0) Alias('test0', test0) +Alias('bootdesc', bootdesc) -Default([mm0, fs0, libposix, test0]) +Default([mm0, fs0, libposix, test0, bootdesc]) diff --git a/conts/posix/bootdesc/SConscript b/conts/posix/bootdesc/SConscript index 6dd82a5..23f871e 100644 --- a/conts/posix/bootdesc/SConscript +++ b/conts/posix/bootdesc/SConscript @@ -3,31 +3,26 @@ # 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 -# . -# -# Author: Russel Winder import os.path -import subprocess -import shutil +import sys, subprocess, shutil +from os.path import * -Import('environment', 'images') +Import('config', 'environment', 'images') e = environment.Clone() -e.Append(LINKFLAGS = ['-T' + e['posixServicesDirectory'] + '/bootdesc/linker.lds']) -e.Append(CPPPATH = ['#' + e['includeDirectory']]) +e.Append(LINKFLAGS = ['-T' + e['bootdesc_dir'] + '/linker.lds']) +#e.Append(LINKFLAGS = ['-T' + '/linker.lds']) -bootdescTemplate = \ +PROJRELROOT = '../../../../' + +sys.path.append(os.path.abspath(PROJRELROOT)) + +from config.projpaths import * +from config.configuration import * +from tools.pyelf import elf + +bootdesc_template = \ ''' /* This file is autogenerated, do not edit by hand. */ @@ -54,7 +49,7 @@ struct bootdesc bootdesc = { }; ''' -imageTemplate = \ +image_template = \ ''' [%s] = { .name = "%s", .phys_start = %s, @@ -62,36 +57,49 @@ imageTemplate = \ }, ''' -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 conv_hex(val): + hexval = hex(val) + if hexval[-1:] == 'L': + hexval = hexval[:-1] + return hexval -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 image_lma_start_end(img): + elffile = elf.ElfFile.from_file(img) + paddr_first = 0 + paddr_start = 0 + paddr_end = 0 + for pheader in elffile.pheaders: + x = pheader.ai + if str(x.p_type) != "LOAD": + continue + if paddr_first == 0: + paddr_first = 1 + paddr_start = x.p_paddr.value + if paddr_start > x.p_paddr.value: + paddr_start = x.p_paddr.value + if paddr_end < x.p_paddr + x.p_memsz: + paddr_end = x.p_paddr + x.p_memsz + return paddr_start, paddr_end -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) +def generate_bootdesc(target, source, env): + with open(target[0].path, 'w+' ) as f: + images_string = '' + for index in range(len(source)): + start, end = image_lma_start_end(source[index].path) + images_string += image_template % (str(index), basename(source[index].path), conv_hex(start), conv_hex(end)) + f.write(bootdesc_template % (len(source), len(source), images_string)) -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']) +def relocate_bootdesc(target, source, env): + bootdesc_raw = source[0] + images = source[1:] + mm0 = images[0] + start, end = image_lma_start_end(mm0.path) + print "arm-none-linux-gnueabi-objcopy --adjust-section-vma .data=" + conv_hex(end) + " " + bootdesc_raw.path + os.system("arm-none-linux-gnueabi-objcopy --adjust-section-vma .data=" + conv_hex(end) + " " + bootdesc_raw.path) + shutil.copyfile(bootdesc_raw.path, target[0].path) + +bootdesc_c = e.Command('bootdesc.c', images, generate_bootdesc) +bootdesc_raw = e.Program('bootdesc_raw.elf', bootdesc_c) +bootdesc = e.Command('bootdesc.elf', [bootdesc_raw, images], relocate_bootdesc) Return('bootdesc') diff --git a/conts/posix/bootdesc/SConstruct b/conts/posix/bootdesc/SConstruct index 7eb14cf..b38e15c 100644 --- a/conts/posix/bootdesc/SConstruct +++ b/conts/posix/bootdesc/SConstruct @@ -8,116 +8,16 @@ import sys import shutil from os.path import join -# The root directory of the repository where this file resides: -project_root = "../.." -tools_root = "../../tools" +builddir = ARGUMENTS.get('builddir', 'build/conts/posix') -kernel = join(project_root, "build/start.axf") -mm0 = join(project_root, "tasks/mm0/mm0.axf") -fs0 = join(project_root, "tasks/fs0/fs0.axf") -test0 = join(project_root, "tasks/test0/test0.axf") -#test1 = join(project_root, "tasks/test1/test1.axf") -#blkdev0 = join(project_root, "tasks/fsbin/blkdev0.axf") - -images = [kernel, mm0, fs0, test0] -autogen_templ = "bootdesc.c.append" - -def get_image_name_start_end(image, target): - ''' - Using readelf.py utility, extracts name, start, end triplet from an arm-elf image. - ''' - rest, name = os.path.split(image) - if name[-4] == ".": - name = name[:-4] - os.system(join(tools_root, "pyelf/readelf.py --lma-start-end " + \ - image + " > " + target)) - -bootdesc_template = \ -''' -struct bootdesc bootdesc = { - .desc_size = sizeof(struct bootdesc) + sizeof(struct svc_image) * %s, - .total_images = %s, - .images = { -%s - }, -}; -''' - -images_template = \ -''' [%s] = { - .name = "%s", - .phys_start = %s, - .phys_end = %s, - }, -''' - -images_template_end = \ -''' - }, -''' - -def generate_bootdesc(source, target, env): - ''' - Extracts name, start, end information from the kernel and each svc task. - Uses this information to produce bootdesc.c - ''' - source.sort() - images = [] - images_string = "" - for node in source: - if str(node)[-4:] == ".axf": - rest, imgname = os.path.split(str(node)) - images.append((str(node), imgname[:-4])) - elif str(node) [-6:] == ".templ": - # Static template that has type definitions. - #rest, original_template = os.path.split(str(node)) - original_template = str(node) - index = 0 - for imgpath, imgname in images: - get_image_name_start_end(imgpath, imgname + ".txt") - if imgname != "start": - f = open(imgname + ".txt", "r") - svc_name = f.readline()[:-1] - [start, startval] = str.split(f.readline()[:-1]) - [end, endval] = str.split(f.readline()[:-1]) - f.close() - images_string += images_template % (str(index), svc_name, \ - hex(int(startval, 16)), hex(int(endval, 16))) - index += 1 - - # Autogenerated template with actual data. - autogen_template = open(autogen_templ, "w+") - autogen_template.write(bootdesc_template % (str(index), str(index), images_string)) - autogen_template.close() - - os.system("cat " + original_template + " > " + str(target[0])) - os.system("cat " + autogen_templ + " >> " + str(target[0])) - -def relocate_bootdesc(source, target, env): - f = open("start.txt", "r") - kernel_name = f.readline()[:-1] - [start, startval] = str.split(f.readline()[:-1]) - [end, endval] = str.split(f.readline()[:-1]) - os.system("arm-none-linux-gnueabi-objcopy --adjust-section-vma .data=" + \ - hex(int(endval,16)) + " " + str(source[0])) - os.system("mv " + str(source[0]) + " " + str(target[0])) -# The kernel build environment: env = Environment(CC = 'arm-none-linux-gnueabi-gcc', - # We don't use -nostdinc because sometimes we need standard headers, - # such as stdarg.h e.g. for variable args, as in printk(). CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', '-Werror'], LINKFLAGS = ['-nostdlib','-Tlinker.lds'], ASFLAGS = ['-D__ASSEMBLY__'], - PROGSUFFIX = '.axf', # The suffix to use for final executable - ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path - LIBS = 'gcc', # libgcc.a - This is required for division routines. - CPPPATH = '#include') # `hash' ('#') is a shorthand meaning `relative to - # the root directory'. But this only works for - # well-defined variables, not all paths, and only - # if we use a relative build directory for sources. + PROGSUFFIX = '.elf', + ENV = {'PATH' : os.environ['PATH']}, + LIBS = 'gcc', + CPPPATH = '#include') -bootdesc_src = env.Command("bootdesc.c", ["bootdesc.c.templ"] + images, generate_bootdesc) -objs = env.Object('bootdesc.c') -bootdesc = env.Program('bootdesc_data', objs) -bootdesc_relocated = env.Command("bootdesc.axf", "bootdesc_data.axf", relocate_bootdesc) -env.Depends(bootdesc_relocated, bootdesc) +bootdesc = env.Program(join(builddir, 'bootdesc.elf'), join(builddir, 'bootdesc.c')) +Default(bootdesc) diff --git a/conts/posix/bootdesc/bootdesc.c.templ b/conts/posix/bootdesc/bootdesc.template.in similarity index 100% rename from conts/posix/bootdesc/bootdesc.c.templ rename to conts/posix/bootdesc/bootdesc.template.in diff --git a/scripts/conts/containers.py b/scripts/conts/containers.py index fa2f1fe..bc7a90a 100755 --- a/scripts/conts/containers.py +++ b/scripts/conts/containers.py @@ -30,6 +30,9 @@ def build_linux_container(projpaths, container): rootfs_builder) return linux_container_packer.pack_container() +def build_posix_container(projpaths, container): + posix_builder = PosixBuilder(projpaths, container) + posix_builder.build_posix() def glob_by_walk(arg, dirname, names): ext, imglist = arg @@ -61,6 +64,8 @@ def build_all_containers(): cont_images.append(build_linux_container(projpaths, container)) elif container.type == 'bare': cont_images.append(build_default_container(projpaths, container)) + elif container.type == 'posix': + cont_images.append(build_posix_container(projpaths, container)) else: print "Error: Don't know how to build " + \ "container of type: %s" % (container.type) diff --git a/tools/pyelf/readelf.py b/tools/pyelf/readelf.py index 510e976..2fdadd5 100755 --- a/tools/pyelf/readelf.py +++ b/tools/pyelf/readelf.py @@ -58,71 +58,6 @@ def main(): print "Afterburn:" for burn in burns: print " ", burn - if options.lma_boundary: - paddr_first = 0 - paddr_start = 0 - paddr_end = 0 - for pheader in elffile.pheaders: - x = pheader.ai - if str(x.p_type) != "LOAD": - continue - # First time assign the first p_paddr. - if paddr_first == 0: - paddr_first = 1 - paddr_start = x.p_paddr.value - # Then if new paddr is lesser, reassign start. - if paddr_start > x.p_paddr.value: - paddr_start = x.p_paddr.value - # If end of segment is greater, reassign end. - if paddr_end < x.p_paddr + x.p_memsz: - paddr_end = x.p_paddr + x.p_memsz - rest, image_name = path.split(args[0]) - if image_name[-4] == ".": - image_name = image_name[:-4] - print image_name - if hex(paddr_start)[-1] == "L": - print "image_start " + hex(paddr_start)[:-1] - else: - print "image_start " + hex(paddr_start) - if hex(paddr_end)[-1] == "L": - print "image_end " + hex(paddr_end)[:-1] - else: - print "image_end " + hex(paddr_end) - - if options.ffpage: - paddr_max = 0 - p_align = 0 - for pheader in elffile.pheaders: - x = pheader.ai - if str(x.p_type) == "LOAD": - paddr = x.p_paddr + x.p_memsz - p_align = x.p_align - if paddr > paddr_max: - paddr_max = paddr - - print "/*\n" + \ - " * The next free p_align'ed LMA base address\n" + \ - " *\n" + \ - " * p_align = " + hex(p_align.value) + "\n" + \ - " *\n" + \ - " * Recap from ELF spec: p_align: Loadable process segments must have\n" + \ - " * congruent values for p_vaddr and p_offset, modulo the page size. \n" + \ - " * This member gives the value to which the segments are aligned in \n" + \ - " * memory and in the file. Values 0 and 1 mean that no alignment is \n" + \ - " * required. Otherwise, p_align should be a positive, integral power\n" + \ - " * of 2, and p_addr should equal p_offset, modulo p_align. \n" + \ - " * This essentially means next available address must be aligned at\n" + \ - " * p_align, rather than the page_size, which one (well, I) would \n" + \ - " * normally expect. \n" + \ - " */\n" - paddr_aligned = paddr_max & ~(p_align.value - 1) - if paddr_max & (p_align.value - 1): - paddr_aligned += p_align.value - if hex(paddr_aligned)[-1] == "L": - print "physical_base = " + hex(paddr_aligned)[:-1] + ";" - else: - print "physical_base = " + hex(paddr_aligned) + ";" - if __name__ == "__main__": main()