Bootdesc building working

This commit is contained in:
Bahadir Balban
2009-09-30 16:31:34 +03:00
parent 1aa31bc9d5
commit 73225a0119
7 changed files with 85 additions and 223 deletions

View File

@@ -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
}

View File

@@ -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])

View File

@@ -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
# <http://www.gnu.org/licenses/>.
#
# 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')

View File

@@ -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)

View File

@@ -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)

View File

@@ -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()