# -*- 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 # . # # Author: Russel Winder import os.path import subprocess Import('environment', 'images') def ksymToLds(target, source, env): symbols = ['break_virtual'] with open(target[0].path, 'w') as asmFile: asmFile.write(''' /* * %s autogenerated from %s * * This file is included by the loader sources so that any * kernel symbol address can be known in advance and stopped * at by debuggers before virtual memory is enabled. */ ''' % (target[0].name, source[0].name)) for symbol in symbols: process = subprocess.Popen('arm-none-eabi-objdump -d ' + source[0].path + ' | grep "<' + symbol + '>"', shell=True, stdout=subprocess.PIPE) assert process.wait() == 0 address, name = process.stdout.read().split() assert '<' + symbol + '>:' == name asmFile.write( ''' .section .text .align 4 .global %s .type %s, function .equ %s, %s ''' % (symbol, symbol, symbol, (hex(int(address, 16) - 0xf0000000))[:-1])) def createKernelSFile(target, source, env): with open(target[0].path, 'w') as asmFile: asmFile.write(''' /* This file defines kernel symbols extracted from the kernel image in their physical address */ .include "%s" .section .kernel .incbin "%s" ''' % (source[0].path , source[1].path)) for image in source[2:]: asmFile.write(''' .align 4 .section .%s .incbin "%s" ''' % (os.path.splitext(image.name)[0], image.path)) def createMainC(target, source, env): with open(source[0].path) as inFile: with open(target[0].path, 'w') as outFile: externs = '' declarations = '' loads = '' for item in source[1:]: name = os.path.splitext(item.name)[0] if name == 'start' : name = 'kernel' externs += ''' extern char _start_%s[]; extern char _end_%s[]; ''' % (name, name) declarations += ' void *%s_entry = NULL;\n' % (name,) loads += ''' printf("Loading the %s...\\n"); load_image(&%s_entry, _start_%s, _end_%s); ''' %(name, name, name, name) text = inFile.read() text = text.replace('__EXTERNAL_SYMBOLS_EDIT_MARKER__', externs) text = text.replace('__DECLARATIONS_EDIT_MARKER__', declarations) text = text.replace('__LOAD_STATEMENTS_EDIT_MARKER__', loads) outFile.write(text) def createLinkerScript(target, source, env): with open(source[0].path) as inFile: with open(target[0].path, 'w') as outFile: linkerItems = '' for item in source[1:]: name = os.path.splitext(item.name)[0] if name == 'start' : name = 'kernel' linkerItems += ''' _start_%s = .; *(.%s) _end_%s = .; ''' % (name, name, name) outFile.write(inFile.read().replace('__LINKER_ITEMS_EDIT_MARKER__', linkerItems)) startAxfS = Command('start.axf.S', images[0], ksymToLds) kernelS = Command('kernel.S', [startAxfS] + images, createKernelSFile) # Order of dependencies is crucial here. mainC = Command('main.c', ['main.c.in'] + images, createMainC) linkerScript = Command('linker.lds', ['linker.lds.in'] + images, createLinkerScript) objects = environment.Object(['arch.c' , kernelS, startAxfS, mainC]) Depends(objects, environment['configFiles']) Depends(objects, images) program = environment.Program('final', objects + [environment['baremetal_crt0']]) Depends(program, linkerScript) Return('program')