switch-coreboot/util/config/NLBConfig.py
2000-12-19 03:12:51 +00:00

487 lines
14 KiB
Python

#! /usr/bin/python
import sys
import os
import re
import string
debug = 0;
makeoptions = {};
# rule format. Key is the rule name. value is a list of lists. The first
# element of the list is the dependencies, the rest are actions.
makebaserules = {};
treetop = '';
outputdir = '';
# config variables for the ldscript
data = 0x4000;
bss = 0x5000;
stack = 0x90000;
linuxbiosbase = 0xf0000;
objectrules = [];
userrules = [];
# this is the absolute base rule, and so is very special.
mainrulelist = "all"
def add_main_rule_dependency(new_dependency):
global mainrulelist
mainrulelist = mainrulelist + ' ' + new_dependency
# function to add an object to the set of objects to be made.
# this is a tuple, object name, source it depends on,
# and an optional rule (can be empty) for actually building
# the object
def addobject(object, sourcepath, rule):
objectrules.append([object, sourcepath, rule])
# OK, let's face it, make sucks.
# if you have a rule like this:
# a.o: /some/long/path/a.c
# make won't apply the .c.o rule. Toy!
def addobject_defaultrule(object, sourcepath):
defaultrule = "\t cc -c $(CFLAGS) $(CPUFLAGS) $<"
objectrules.append([object, sourcepath, defaultrule])
# for all these functions, you need:
# the dir that the Config file is in
# the treetop (so make it global!)
# the name
# Functions used by commands
def top(dir, top_name):
command_vals['TOP'] = top_name
def target(dir, targ_name):
global outputdir
outputdir = targ_name
if os.path.isdir(outputdir):
print 'Will place Makefile, crt0.S, ldscript.ld in ', outputdir
else:
print outputdir, 'is not a directory. '
print ' I know I should make this, but I\'m too paranoid'
print ' To fix this, type'
print 'mkdir -p ', outputdir
print ' then run this program again'
sys.exit(1)
def handleconfig(dir, type, name):
# seems weird, eh? but config file are always done from
# treetop
dir = os.path.join(treetop, type, name)
file = os.path.join(dir, 'Config')
print "Process config file: ", file
if os.path.isfile(file):
doconfigfile(dir, file)
else:
print "===> Warning: %s not found" % file
def buildfullpath(type, name):
fullpath = os.path.join(type, name)
command_vals[type] = fullpath
return fullpath
def common_command_action(dir, type, name):
fullpath = buildfullpath(type, name)
handleconfig(dir, 'src', fullpath)
return fullpath
def mainboard(dir, mainboard_name):
common_command_action(dir, 'mainboard', mainboard_name)
# old legacy PC junk, which will be dying soon.
def keyboard(dir, keyboard_name):
if (debug):
print "KEYBOARD"
keyboard_dir = os.path.join(treetop, 'src', keyboard_name)
addobject_defaultrule('keyboard.o', keyboard_dir)
def cpu(dir, cpu_name):
common_command_action(dir, 'cpu', cpu_name)
def northsouthbridge(dir, northsouthbridge_name):
fullpath = common_command_action(dir, 'northsouthbridge',
northsouthbridge_name)
command_vals["northbridge"] = [fullpath]
command_vals["southbridge"] = [fullpath]
def northbridge(dir, northbridge_name):
common_command_action(dir, 'northbridge', northbridge_name)
def southbridge(dir, southbridge_name):
common_command_action(dir, 'southbridge', southbridge_name)
def pcibridge(dir, pcibridge_name):
common_command_action(dir, 'picbridge', picbridge_name)
# I don't see a need yet to read in a config file for
# superio. Don't bother.
def superio(dir, superio_name):
# note that superio is w.r.t. treetop
buildfullpath('superio', superio_name)
dir = os.path.join(treetop, 'src', 'superio', superio_name)
addobject_defaultrule('superio.o', dir)
# arg, what's a good way to do this ...
# basically raminit can have a whole list of files. That's why
# this is a list.
def raminit(dir, file):
ramfilelist = command_vals['raminit']
ramfilelist.append(file)
print "Added ram init file: ", file
def object(dir, obj_name):
addobject_defaultrule(obj_name, dir)
# for eventual user-defined rules.
# pattern is name : deps ; rule
# we'll look at adding rules later
def makerule(dir, rule):
wspc = string.whitespace
rest = "(.*)"
w = "[" + wspc + "]*"
cmd = "([^" + wspc + "]*)"
namepat = "(.*)"
pat = cmd + w + ":" + w + namepat + w + ";" + w + rest + w
print "pat :", pat, ":", rule
command_re = re.compile(pat)
m = command_re.match(rule)
rulename = m.group(1)
dependencies = m.group(2)
actions = m.group(3)
print "rulename :", rulename, ": deps:", dependencies,":"
print " actions ", actions
makebaserules[rulename] = [dependencies]
makebaserules[rulename].append(actions)
def addaction(dir, rule):
wspc = string.whitespace
rest = "(.*)"
w = "[" + wspc + "]*"
namepat = "(.*)"
cmd = "([^" + wspc + "]*)"
pat = cmd + w + rest + w
print "pat :", pat, ":", rule
command_re = re.compile(pat)
m = command_re.match(rule)
rulename = m.group(1)
actions = m.group(2)
print "rulename :", rulename
print " actions ", actions
makebaserules[rulename].append(actions)
# add a dependency
def adddepend(dir, rule):
wspc = string.whitespace
rest = "(.*)"
w = "[" + wspc + "]*"
namepat = "(.*)"
cmd = "([^" + wspc + "]*)"
pat = cmd + w + rest + w
print "pat :", pat, ":", rule
command_re = re.compile(pat)
m = command_re.match(rule)
rulename = m.group(1)
depend = m.group(2)
print "rulename :", rulename
print " depend ", depend
makebaserules[rulename][0] = makebaserules[rulename][0] + " " + depend
def makedefine(dir, rule):
userrules.append(rule)
def option(dir, option):
makeoptions[option] = 1;
def nooption(dir, option):
makeoptions[option] = 0;
def commandline(dir, command):
rule = "CMD_LINE=\'\"" + command + "\"\'"
makedefine(dir, rule)
# we do all these rules by hand because docipl will always be special
# it's more or less a stand-alone bootstrap
def docipl(dir, ipl_name):
mainboard = command_vals['mainboard']
mainboard_dir = os.path.join(treetop, 'src', mainboard)
# add the docipl rule
add_main_rule_dependency('docipl')
userrules.append("docipl: ipl.o")
userrules.append("\tobjcopy -O binary -R .note -R .comment -S ipl.o docipl")
# now, add the ipl.o rule
iplpath = os.path.join(treetop, 'src', ipl_name)
userrules.append("ipl.o: " + iplpath)
# Now we need a mainboard-specific include path
userrules.append("\tcc $(CPUFLAGS) -I%s -c $<" % mainboard_dir)
def linux(dir, linux_name):
linuxrule = 'LINUX=' + linux_name
makedefine(dir, linuxrule)
def setdata(dir, address):
data = address
def setbss(dir, address):
bss = address
def setstack(dir, address):
stack = address
def setlinuxbiosbase(dir, address):
linuxbiosbase = address
list_vals = {
# 'option': []
}
# Commands
# some of these command vals need to change to strings
# we have been evolving this as we go ...
command_vals = {
'TOP' : '', # Top of bios source tree
'target' : '', # Target directory for build
'mainboard' : [], # Vendor, Mainboard source directory
'cpu' : {}, # CPU configuration file
'northbridge' : [], # vendor, northbridge name
'southbridge' : [], # vendor, southbridge name
'northsouthbridge' : [], # vendor, northsouthbridge name
'pcibridge' : [], # vendor, bridgename
'superio' : [], # vendor, superio name
'object' : {}, # path/filename.[cS]
'raminit' : [] # set of files to include for ram init
}
command_actions = {
'TOP' : top,
'target' : target,
'mainboard' : mainboard,
'cpu' : cpu,
'northbridge' : northbridge,
'southbridge' : southbridge,
'northsouthbridge' : northsouthbridge,
'pcibridge' : pcibridge,
'superio' : superio,
'object' : object,
'linux' : linux,
'raminit' : raminit,
'keyboard' : keyboard,
'docipl' : docipl,
'makedefine' : makedefine,
'makerule' : makerule,
'addaction' : addaction,
'option' : option,
'nooption' : nooption,
'data' : setdata,
'bss' : setbss,
'stack' : setstack,
'biosbase' : setlinuxbiosbase,
'commandline' : commandline
}
makeobjects = [];
def readfile(filename):
# open file, extract lines, and close
if not os.path.isfile(filename):
print config_file, "is not a file \n"
sys.exit()
fileobject = open(filename, "r")
filelines = fileobject.readlines()
fileobject.close()
return filelines
def doconfigfile(dir, filename):
if (debug):
print "doconfigfile" , filename
filelines = readfile(filename)
if (debug):
print "doconfigfile: filelines", filelines
# parse out command arguments /(.*)(#.*)/ for comments
regexp = re.compile(r"([^#]*)(.*)")
wspc = string.whitespace
command_re = re.compile(r"([^" + wspc + "]*)([" + wspc + "]+)(.*)")
for line in filelines:
line = string.strip(line)
m = regexp.match(line)
command_txt = m.group(1)
# Need to run commands as they come in.
if command_txt:
command = command_re.match(command_txt)
verb = command.group(1)
args = command.group(3)
if command_actions.has_key(verb):
command_actions[verb](dir, args)
elif list_vals.has_key(verb):
list_vals[verb] = list_vals[verb] + [args]
else:
print verb, "is not a valid command! \n"
sys.exit()
# output functions
# write crt0
def writep5crt0(path):
crt0filepath = os.path.join(path, "crt0.S")
raminitfiles = command_vals["raminit"]
paramfile = os.path.join(treetop, 'src/include',
command_vals['northbridge'][0], "param.h")
paramfileinclude = ''
print "Trying to create ", crt0filepath
# try:
file = open(crt0filepath, 'w+')
print "Check for crt0.S param file:", paramfile
if os.path.isfile(paramfile):
ipfile = os.path.join(command_vals['northbridge'][0],"param.h")
paramfileinclude = "#include <%s>\n" % ipfile
print " Adding include to crt0.S for this parameter file:"
print " ", paramfileinclude
# serial for superio
superioserial = "#include <%s/setup_serial.inc>\n" % command_vals['superio']
crt0lines = readfile(crt0base)
if (debug):
print "CRT0 ", crt0lines
for line in crt0lines:
if (string.strip(line) <> "CRT0_PARAMETERS"):
file.write(line)
else:
file.write(paramfileinclude)
# we will do this better at some point.
# possible we need a 'console' command.
file.write("\n");
file.write("#ifdef SERIAL_CONSOLE\n");
file.write(superioserial)
file.write("#include <pc80/serial.inc>\n");
file.write("TTYS0_TX_STRING($ttyS0_test)\n")
file.write("#endif /* SERIAL_CONSOLE */\n")
file.write("\n");
for i in range(len(raminitfiles)):
file.write("#include <%s>\n" % raminitfiles[i])
file.close();
# write ldscript
def writeldscript(path):
ldfilepath = os.path.join(path, "ldscript.ld")
print "Trying to create ", ldfilepath
# try:
file = open(ldfilepath, 'w+')
# print out the ldscript rules
# print out the values of defined variables
file.write('_PDATABASE = 0x%x;\n' % data)
file.write('_RAMBASE = 0x%x;\n' % bss)
file.write('_KERNSTK = 0x%x;\n' % stack)
file.write('_ROMBASE = 0x%x;\n' % linuxbiosbase)
ldlines = readfile(ldscriptbase)
if (debug):
print "LDLINES ",ldlines
for line in ldlines:
file.write(line)
file.close();
# write the makefile
# we're not sure whether to write crt0.S yet. We'll see.
# let's try the Makefile
# first, dump all the -D stuff
def writemakefile(path):
makefilepath = os.path.join(path, "Makefile")
print "Trying to create ", makefilepath
# try:
file = open(makefilepath, 'w+')
file.write("TOP=%s\n" % (treetop))
file.write("CPUFLAGS=\n")
for z in makeoptions.keys():
if (makeoptions[z]):
file.write("CPUFLAGS += -D%s\n" % (z))
else:
file.write("CPUFLAGS += -U%s\n" % (z))
# print out all the object dependencies
# There is ALWAYS a crt0.o
file.write("OBJECTS=crt0.o\n")
for i in range(len(objectrules)):
file.write("OBJECTS += %s\n" % (objectrules[i][0]))
# print out the base rules
# need to have a rule that counts on 'all'
file.write("mainrule: %s\n" % mainrulelist)
# for i in range(len(baserules)):
# file.write("%s\n" % baserules[i])
for i in range(len(userrules)):
file.write("%s\n" % userrules[i])
# print out any user rules
for z in makebaserules.keys():
file.write("%s: %s\n" % (z, makebaserules[z][0]))
for i in range(len(makebaserules[z]) - 1):
file.write("\t%s\n" % makebaserules[z][i+1])
for i in range(len(objectrules)):
base = objectrules[i][0]
base = base[0:len(base)-2]
source = os.path.join(objectrules[i][1], base)
source = source + ".c"
file.write( "%s: %s\n" % (objectrules[i][0], source))
file.write( "%s\n" % objectrules[i][2])
# print out the linux rules
# these go here because some pieces depend on user rules
# for i in range(len(linuxrules)):
# file.write("%s\n" % linuxrules[i])
file.close();
# except IOError:
# print "File open and write failed for ", makefilepath
# ---------------------------------------------------------------------
# MAIN
# ---------------------------------------------------------------------
# Retrieve config filename from command line
if len(sys.argv) != 3:
print "LBConfig <Config Filename> <src-path>\n"
sys.exit()
config_path, config_file = os.path.split(sys.argv[1])
# determine current directory and set default TOP
command_vals['TOP'] = sys.argv[2]
treetop = command_vals['TOP']
# set the default locations for config files
makebase = os.path.join(treetop, "util/config/make.base")
crt0base = os.path.join(treetop, "util/config/p5crt0.base")
ldscriptbase = os.path.join(treetop, "util/config/ldscript.base")
doconfigfile(treetop, sys.argv[1])
# do standard config files that the user need not specify
# for now, this is just 'lib', but it may be more later.
libdir = treetop + "/src/lib"
libconfigfile = libdir + "/Config"
print "Process config file: ", libconfigfile
doconfigfile(libdir, libconfigfile)
# now read in the base files.
print "Now Process the base files"
print "Makebase is :", makebase, ":"
doconfigfile(treetop, makebase)
# print out command values
#print "Command Values:"
#for key,val in command_vals.items():
# print key, val
writemakefile(outputdir)
writeldscript(outputdir)
writep5crt0(outputdir)