X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=util%2Fnewconfig%2Fconfig.g;h=02e04b1ff6b26746f0cb06477ee1df650021f4ee;hb=483b7bbd7703ebe100ea7b10393e18712bbafc95;hp=b620f63d27f48d6fc9d16a622eb0cca8f7d345f4;hpb=c361a6b218e89df9a939c9a57054df38759a55c2;p=coreboot.git diff --git a/util/newconfig/config.g b/util/newconfig/config.g index b620f63d2..02e04b1ff 100644 --- a/util/newconfig/config.g +++ b/util/newconfig/config.g @@ -1,33 +1,44 @@ +# -*- python -*- import sys import os import re import string +import types + +import traceback -debug = 0 warnings = 0 errors = 0 target_dir = '' target_name = '' treetop = '' +full_mainboard_path = '' +mainboard_path = '' global_options = {} global_options_by_order = [] global_option_values = {} global_uses_options = {} +global_exported_options = [] romimages = {} buildroms = [] +rommapping = {} curimage = 0 +bootblocksize = 0 alloptions = 0 # override uses at top level local_path = re.compile(r'^\.') include_pattern = re.compile(r'%%([^%]+)%%') +# the cpu type for this mainboard +cpu_type = 0 + # ----------------------------------------------------------------------------- # Utility Classes # ----------------------------------------------------------------------------- -# Used to keep track of the current part or dir class stack: + """Used to keep track of the current part or dir""" class __stack_iter: def __init__ (self, stack): self.index = 0 @@ -51,10 +62,7 @@ class stack: return len(self.stack) def __getitem__ (self, i): - try: - return self.stack[i] - except IndexError: - return 0 + return self.stack[i] def __iter__ (self): return self.__stack_iter(self.stack) @@ -79,13 +87,40 @@ class stack: partstack = stack() dirstack = stack() +class debug_info: + none = 0 + gencode = 1 + dumptree = 2 + object = 3 + dict = 4 + statement = 5 + dump = 6 + gengraph = 7 + + def __init__(self, *level): + self.__level = level + + def setdebug(self, *level): + self.__level = level + + def level(self, level): + return level in self.__level + + def info(self, level, str): + if level in self.__level: + print str + +global debug +debug = debug_info(debug_info.dumptree) +debug = debug_info(debug_info.object) + # ----------------------------------------------------------------------------- # Error Handling # ----------------------------------------------------------------------------- -# Used to keep track of our current location while parsing -# configuration files class location: + """Used to keep track of our current location while parsing + configuration files""" class __place: def __init__(self, file, line, command): self.file = file @@ -131,58 +166,108 @@ class location: return self.stack.tos().at() loc = location() -# Print error message def error(string): + """Print error message""" global errors, loc errors = errors + 1 print "===> ERROR: %s" % string print "%s" % loc -# Print error message and exit def fatal(string): + """Print error message and exit""" error(string) exitiferrors() -# Print warning message def warning(string): + """Print warning message""" global warnings, loc warnings = warnings + 1 - print "===> Warning: %s" % string - print "%s" % loc + print "===> WARNING: %s" % string + +def notice(string): + """Print notice message""" + #print "===> NOTE: %s" % string -# Exit parser if an error has been encountered def exitiferrors(): + """Exit parser if an error has been encountered""" if (errors != 0): sys.exit(1) -def debug_print(level, str): - global debug - if (debug >= level): - print str +def safe_open(file, mode): + try: + return open(file, mode) + except IOError: + fatal("Could not open file \"%s\"" % file) # ----------------------------------------------------------------------------- # Main classes # ----------------------------------------------------------------------------- -# A rom image is the ultimate goal of linuxbios class romimage: + """A rom image is the ultimate goal of coreboot""" def __init__ (self, name): + # name of this rom image self.name = name + + # set by 'arch' directive self.arch = '' + + # set by 'payload' directive self.payload = '' + + # set by 'init' directive self.initfile = '' + + # make rules added by 'makerule' directive self.makebaserules = {} + + # object files added by 'object' directive self.objectrules = {} + + # init object files added by 'initobject' directive self.initobjectrules = {} + + # driver files added by 'driver' directive self.driverrules = {} + + # smm object files added by 'smmobject' directive + self.smmobjectrules = {} + + # loader scripts added by 'ldscript' directive self.ldscripts = [] + + # user defines added by 'makedefine' directive self.userdefines = [] + + # files to be included in crt0.S self.initincludes = {} - self.useinitincludes = 0 # transitional + + # as above, but order is preserved + self.initincludesorder = [] + + # transitional flag to support old crtinclude format + self.useinitincludes = 0 + + # instance counter for parts self.partinstance = 0 + + # chip config files included by the 'config' directive + self.configincludes = {} + + # root of part tree self.root = 0 + + # name of target directory specified by 'target' directive self.target_dir = '' - self.values = {} # values of options set in romimage + + # option values used in rom image + self.values = {} + + # exported options + self.exported_options = [] + + # Last device built + self.last_device = 0 def getname(self): return self.name @@ -194,8 +279,11 @@ class romimage: self.arch = arch def setpayload(self, payload): + global rommapping self.payload = payload + rommapping[self.name] = payload + def setinitfile(self, initfile): self.initfile = initfile @@ -205,7 +293,7 @@ class romimage: def addmakerule(self, id): o = getdict(self.makebaserules, id) if (o): - print "Warning, rule %s previously defined" % id + warning("rule %s previously defined" % id) o = makerule(id) setdict(self.makebaserules, id, o) @@ -216,7 +304,7 @@ class romimage: o = getdict(self.makebaserules, id) if (o): return o - fatal("No such make rule \"%s\"" % id); + fatal("No such make rule \"%s\"" % id) def addmakeaction(self, id, str): o = getdict(self.makebaserules, id) @@ -224,7 +312,7 @@ class romimage: a = dequote(str) o.addaction(a) return - fatal("No such rule \"%s\" for addmakeaction" % id); + fatal("No such rule \"%s\" for addmakeaction" % id) def addmakedepend(self, id, str): o = getdict(self.makebaserules, id) @@ -232,7 +320,7 @@ class romimage: a = dequote(str) o.adddependency(a) return - fatal("No such rule \"%s\" for addmakedepend" % id); + fatal("No such rule \"%s\" for addmakedepend" % id) # this is called with an an object name. # the easiest thing to do is add this object to the current @@ -245,16 +333,23 @@ class romimage: if (suffix == '.o'): suffix = '.c' base = object_name[:-2] + type = object_name[-1:] if (object_name[0] == '.'): source = base + suffix + object = base + '.o' + rel_base = base else: - source = os.path.join(dirstack.tos(), base + suffix) - object = base + '.o' - debug_print(1, "add object %s source %s" % (object_name, source)) - l = getdict(dict, base) + rel_base = re.sub(treetop, "", os.path.join(dirstack.tos(), base)) + source = "$(TOP)/" + rel_base + suffix + if (rel_base[0] == '/'): + rel_base = re.sub("^/", "", rel_base) + object = rel_base + '.o' + + debug.info(debug.object, "add object %s source %s" % (object, source)) + l = getdict(dict, rel_base) if (l): - print "Warning, object/driver %s previously defined" % base - setdict(dict, base, [object, source]) + warning("object/driver %s previously defined" % rel_base) + setdict(dict, rel_base, [object, source, type, rel_base]) def addinitobjectrule(self, name): self.addobjectdriver(self.initobjectrules, name) @@ -265,6 +360,9 @@ class romimage: def adddriverrule(self, name): self.addobjectdriver(self.driverrules, name) + def addsmmobjectrule(self, name): + self.addobjectdriver(self.smmobjectrules, name) + def getinitobjectrules(self): return self.initobjectrules @@ -272,7 +370,7 @@ class romimage: o = getdict(self.initobjectrules, name) if (o): return o - fatal("No such init object rule \"%s\"" % name); + fatal("No such init object rule \"%s\"" % name) def getobjectrules(self): return self.objectrules @@ -281,7 +379,7 @@ class romimage: o = getdict(self.objectrules, name) if (o): return o - fatal("No such object rule \"%s\"" % name); + fatal("No such object rule \"%s\"" % name) def getdriverrules(self): return self.driverrules @@ -290,7 +388,16 @@ class romimage: o = getdict(self.driverrules, name) if (o): return o - fatal("No such driver rule \"%s\"" % name); + fatal("No such driver rule \"%s\"" % name) + + def getsmmobjectrules(self): + return self.smmobjectrules + + def getsmmobjectrule(self, name): + o = getdict(self.smmobjectrules, name) + if (o): + return o + fatal("No such smm object rule \"%s\"" % name) def addldscript(self, path): self.ldscripts.append(path) @@ -308,27 +415,34 @@ class romimage: if (str != 0): self.useinitincludes = 1 - debug_print(2, "ADDCRT0: %s -> %s" % (str, path)) + debug.info(debug.object, "ADDCRT0: %s -> %s" % (str, path)) o = getdict(self.initincludes, path) if (o): - print "Warning, init include for %s previously defined" % path + warning("init include for %s previously defined" % path) o = initinclude(str, path) setdict(self.initincludes, path, o) + self.initincludesorder.append(path) def getinitincludes(self): - return self.initincludes + return self.initincludesorder def getinitinclude(self, path): o = getdict(self.initincludes, path) if (o): return o - fatal("No such init include \"%s\"" % path); + fatal("No such init include \"%s\"" % path) + + def addconfiginclude(self, part, path): + setdict(self.configincludes, part, path) + + def getconfigincludes(self): + return self.configincludes def getincludefilename(self): if (self.useinitincludes): return "crt0.S" else: - return "crt0_include.h" + return "crt0_includes.h" def newformat(self): return self.useinitincludes @@ -353,36 +467,21 @@ class romimage: def gettargetdir(self): return self.targetdir -# A buildrom statement class buildrom: - def __init__ (self, size, roms): + """A buildrom statement""" + def __init__ (self, filename, size, roms): + self.name = filename self.size = size self.roms = roms + + def __len__ (self): + return len(self.roms) + + def __getitem__(self,i): + return self.roms[i] -# this is called with an an object name. -# the easiest thing to do is add this object to the current -# component. -# such kludgery. If the name starts with '.' then make the -# dependency be on ./thing.x gag me. -def addobjectdriver(dict, object_name): - global dirstack - suffix = object_name[-2:] - if (suffix == '.o'): - suffix = '.c' - base = object_name[:-2] - if (object_name[0] == '.'): - source = base + suffix - else: - source = os.path.join(dirstack.tos(), base + suffix) - object = base + '.o' - debug_print(1, "add object %s source %s" % (object_name, source)) - l = getdict(dict, base) - if (l): - print "Warning, object/driver %s previously defined" % base - setdict(dict, base, [object, source]) - -# include file for initialization code class initinclude: + """include file for initialization code""" def __init__ (self, str, path): self.string = str self.path = path @@ -393,8 +492,8 @@ class initinclude: def getpath(self): return self.path -# Rule to be included in Makefile class makerule: + """Rule to be included in Makefile""" def __init__ (self, target): self.target = target self.dependency = [] @@ -415,58 +514,17 @@ class makerule: def gaction(self): return self.actions -# Configuration option class option: + """Configuration option""" def __init__ (self, name): self.name = name # name of option self.loc = 0 # current location - self.set = 0 # option has been set - self.used = 0 # option has been set - self.default = 0 # option has default value (otherwise + self.used = 0 # option has been used # it is undefined) self.comment = '' # description of option self.exportable = 0 # option is able to be exported - self.exported = 0 # option is exported - self.defined = 0 # option has a value self.format = '%s' # option print format - - def setvalue(self, value, values, loc): - self.set = 1 - self.defined = 1 - self.loc = loc - #self.value = value - setdict(values, self.name, value) - - def getvalue(self, image, values): - global curimage - v = getdict(values, self.name) - if (v == 0): - return 0 - val = v.contents() - if (not (type(val) is str)): - return v - if (val == '' or val[0] != '{'): - return v - s = curimage - curimage = image - val = parse('delexpr', val) - curimage = s - # TODO: need to check for parse errors! - return option_value(val) - - def setdefault(self, value, loc): - global global_option_values - if (self.default): - fatal("Error: default value for %s already set" % self.name) - setdict(global_option_values, self.name, value) - self.defined = 1 - self.default = 1 - self.loc = loc - - def setnodefault(self, loc): - self.default = 1 - self.defined = 0 - self.loc = loc + self.write = [] # parts that can set this option def where(self): return self.loc @@ -481,13 +539,8 @@ class option: def setexportable(self): self.exportable = 1 - def setexported(self): - self.exportable = 1 - self.exported = 1 - def setnoexport(self): self.exportable = 0 - self.exported = 0 def setformat(self, fmt): self.format = fmt @@ -500,142 +553,468 @@ class option: self.exported = 1 self.used = 1 - def isexported(self): - return (self.exported and self.defined) - -# def isdefined(self): -# return (self.defined) + def setwrite(self, part): + self.write.append(part) - def isset(self): - return (self.set) + def isexportable(self): + return self.exportable -# def isused(self): -# return (self.used) + def iswritable(self, part): + return (part in self.write) class option_value: - def __init__(self, value): + """Value of a configuration option. The option has a default + value which can be changed at any time. Once an option has been + set the default value is no longer used.""" + def __init__(self, name, prev): + self.name = name + self.value = '' + self.set = 0 + if (prev): + self.value = prev.value + self.set = prev.set + + + def setvalue(self, value): + if ((self.set & 2) == 2): + warning("Changing option %s" % self.name) + else: + self.set |= 2 self.value = value + def setdefault(self, value): + if ((self.set & 1) == 1): + notice("Changing default value of %s" % self.name) + + if ((self.set & 2) == 0): + self.value = value + self.set |= 1 + def contents(self): return self.value -# A configuration part + def isset(self): + return (self.set & 2) == 2 + + class partobj: - def __init__ (self, image, dir, parent, type, name): - debug_print(1, "partobj dir %s parent %s type %s" %(dir,parent,type)) + """A configuration part""" + def __init__ (self, image, dir, parent, part, type_name, instance_name, chip_or_device): + debug.info(debug.object, "partobj dir %s parent %s part %s" \ + % (dir, parent, part)) + + # romimage that is configuring this part self.image = image + + # links for static device tree self.children = 0 + self.prev_sibling = 0 + self.next_sibling = 0 + self.prev_device = 0 + self.next_device = 0 + self.chip_or_device = chip_or_device + + # list of init code files self.initcode = [] - self.registercode = [] - # sibling is not a list. - self.siblings = 0 - self.type = type + + # initializers for static device tree + self.registercode = {} + + # part name + self.part = part + + # type name of this part + self.type_name = type_name + + # object files needed to build this part self.objects = [] + + # directory containg part files self.dir = dir - self.irq = 0 + + # instance number, used to distinguish anonymous + # instances of this part self.instance = image.newpartinstance() - self.flatten_name = flatten_name(type + "/" + name) - debug_print(1, "INSTANCE %d" % self.instance) - self.devfn = 0 - self.private = 0 + debug.info(debug.object, "INSTANCE %d" % self.instance) + + # Options used by this part self.uses_options = {} - # chip initialization. If there is a chip.h in the - # directory, generate the structs etc. to - # initialize the code - if (os.path.exists(dir + "/" + "chip.h")): - self.chipconfig = 1 + + # Name of chip config file (0 if not needed) + self.chipconfig = 0 + + # Flag to indicate that we have generated type + # definitions for this part (only want to do it once) + self.done_types = 0 + + # Path to the device + self.path = "" + + # Resources of the device + self.resoruce = "" + self.resources = 0 + + # Enabled state of the device + self.enabled = 1 + + # Flag if I am a dumplicate device + self.dup = 0 + + # If no instance name is supplied then generate + # a unique name + if (instance_name == 0): + self.instance_name = self.type_name + \ + "_dev%d" % self.instance + self.chipinfo_name = "%s_info_%d" \ + % (self.type_name, self.instance) else: - self.chipconfig = 0 - - if (parent): - debug_print(1, "add to parent") + self.instance_name = instance_name + self.chipinfo_name = "%s_info_%d" % (self.instance_name, self.instance) + + # Link this part into the device list + if (self.chip_or_device == 'device'): + if (image.last_device): + image.last_device.next_device = self + self.prev_device = image.last_device + image.last_device = self + + # Link this part into the tree + if (parent and (part != 'arch')): + debug.info(debug.gencode, "add to parent") self.parent = parent # add current child as my sibling, # me as the child. if (parent.children): - debug_print(1, "add %s (%d) as sibling" % (parent.children.dir, parent.children.instance)) - self.siblings = parent.children - parent.children = self + debug.info(debug.gencode, "add %s (%d) as sibling" % (parent.children.dir, parent.children.instance)) + youngest = parent.children + while(youngest.next_sibling): + youngest = youngest.next_sibling + youngest.next_sibling = self + self.prev_sibling = youngest + else: + parent.children = self else: self.parent = self + + def info(self): + return "%s: %s" % (self.part, self.type) + def type(self): + return self.chip_or_device + + def readable_name(self): + name = "" + name = "%s_%d" % (self.type_name, self.instance) + if (self.chip_or_device == 'chip'): + name = "%s %s %s" % (name, self.part, self.dir) + else: + name = "%s %s" % (name, self.path) + return name + + def graph_name(self): + name = "{ {_dev%d|" % self.instance + if (self.part): + name = "%s%s" % (name, self.part) + else: + name = "%s%s" % (name, self.chip_or_device) + if (self.type_name): + name = "%s}|%s}" % (name, self.type_name) + else: + name = "%s}|%s}" % (name, self.parent.type_name) + return name + def dumpme(self, lvl): - print "%d: type %s" % (lvl, self.type) + """Dump information about this part for debugging""" + print "%d: %s" % (lvl, self.readable_name()) + print "%d: part %s" % (lvl, self.part) print "%d: instance %d" % (lvl, self.instance) + print "%d: chip_or_device %s" % (lvl, self.chip_or_device) print "%d: dir %s" % (lvl,self.dir) - print "%d: flatten_name %s" % (lvl,self.flatten_name) - print "%d: parent %s" % (lvl,self.parent.type) - print "%d: parent dir %s" % (lvl,self.parent.dir) + print "%d: type_name %s" % (lvl,self.type_name) + print "%d: parent: %s" % (lvl, self.parent.readable_name()) if (self.children): - print "%d: child %s" % (lvl, self.children.dir) - if (self.siblings): - print "%d: siblings %s" % (lvl, self.siblings.dir) + print "%d: child %s" % (lvl, self.children.readable_name()) + if (self.next_sibling): + print "%d: siblings %s" % (lvl, self.next_sibling.readable_name()) print "%d: initcode " % lvl for i in self.initcode: - print " %s" % i + print "\t%s" % i print "%d: registercode " % lvl - for i in self.registercode: - print " %s" % i + for f, v in self.registercode.items(): + print "\t%s = %s" % (f, v) print "\n" - def gencode(self, file): - if (self.chipconfig): - file.write("struct %s_config %s_config_%d" % (\ - self.flatten_name ,\ - self.flatten_name , \ - self.instance)) - if (self.registercode): - file.write("\t= {\n") - for i in self.registercode: - file.write( "\t %s" % i) - file.write("\t}\n") + def firstchilddevice(self): + """Find the first device in the children link.""" + kid = self.children + while (kid): + if (kid.chip_or_device == 'device'): + return kid else: - file.write(";") - file.write("\n"); - if (self.instance): - file.write("struct chip dev%d = {\n" % self.instance) - else: - file.write("struct chip root = {\n") - file.write("/* %s %s */\n" % (self.type, self.dir)) - #file.write(" .devfn = %d,\n" % self.devfn) - if (self.siblings): - file.write(" .next = &dev%d,\n" % self.siblings.instance) - if (self.children): - file.write(" .children = &dev%d,\n" % \ - self.children.instance) - if (self.private): - file.write(" .private = private%d,\n" % self.instance) - if (self.chipconfig): - # set the pointer to the structure for all this - # type of part - file.write(" .control= &%s_control,\n" % \ - self.flatten_name ) - # generate the pointer to the isntance - # of the chip struct - file.write(" .chip_config = (void *) &%s_config_%d,\n" %\ - (self.flatten_name, self.instance )) + kid = kid.children + return 0 + + def firstparentdevice(self): + """Find the first device in the parent link.""" + parent = self.parent + while (parent and (parent.parent != parent) and (parent.chip_or_device != 'device')): + parent = parent.parent + if ((parent.parent != parent) and (parent.chip_or_device != 'device')): + parent = 0 + while(parent and (parent.dup == 1)): + parent = parent.prev_sibling + if (not parent): + fatal("Device %s has no device parent; this is a config file error" % self.readable_name()) + return parent + + def firstparentdevicelink(self): + """Find the first device in the parent link and record which link it is.""" + link = 0 + parent = self.parent + while (parent and (parent.parent != parent) and (parent.chip_or_device != 'device')): + parent = parent.parent + if ((parent.parent != parent) and (parent.chip_or_device != 'device')): + parent = 0 + while(parent and (parent.dup == 1)): + parent = parent.prev_sibling + link = link + 1 + if (not parent): + fatal("Device %s has no device parent; this is a config file error" % self.readable_name()) + return link + + + def firstparentchip(self): + """Find the first chip in the parent link.""" + parent = self.parent + while (parent): + if ((parent.parent == parent) or (parent.chip_or_device == 'chip')): + return parent + else: + parent = parent.parent + fatal("Device %s has no chip parent; this is a config file error" % self.readable_name()) + + def firstsiblingdevice(self): + """Find the first device in the sibling link.""" + sibling = self.next_sibling + while(sibling and (sibling.path == self.path)): + sibling = sibling.next_sibling + if ((not sibling) and (self.parent.chip_or_device == 'chip')): + sibling = self.parent.next_sibling + while(sibling): + if (sibling.chip_or_device == 'device'): + return sibling + else: + sibling = sibling.children + return 0 + + def gencode(self, file, pass_num): + """Generate static initalizer code for this part. Two passes + are used - the first generates type information, and the second + generates instance information""" + if (pass_num == 0): + if (self.chip_or_device == 'chip'): + return; + else: + if (self.instance): + file.write("struct device %s;\n" \ + % self.instance_name) + else: + file.write("struct device dev_root;\n") + return + # This is pass the second, which is pass number 1 + # this is really just a case statement ... + + if (self.chip_or_device == 'chip'): + if (self.chipconfig): + debug.info(debug.gencode, "gencode: chipconfig(%d)" % \ + self.instance) + file.write("struct %s_config %s" % (self.type_name ,\ + self.chipinfo_name)) + if (self.registercode): + file.write("\t= {\n") + for f, v in self.registercode.items(): + file.write( "\t.%s = %s,\n" % (f, v)) + file.write("};\n") + else: + file.write(";") + file.write("\n") + + if (self.instance == 0): + self.instance_name = "dev_root" + file.write("struct device **last_dev_p = &%s.next;\n" % (self.image.last_device.instance_name)) + file.write("struct device dev_root = {\n") + file.write("\t.ops = &default_dev_ops_root,\n") + file.write("\t.bus = &dev_root.link[0],\n") + file.write("\t.path = { .type = DEVICE_PATH_ROOT },\n") + file.write("\t.enabled = 1,\n\t.links = 1,\n") + file.write("\t.on_mainboard = 1,\n") + file.write("\t.link = {\n\t\t[0] = {\n") + file.write("\t\t\t.dev=&dev_root,\n\t\t\t.link = 0,\n") + file.write("\t\t\t.children = &%s,\n" % self.firstchilddevice().instance_name) + file.write("\t\t},\n") + file.write("\t},\n") + if (self.chipconfig): + file.write("\t.chip_ops = &%s_ops,\n" % self.type_name) + file.write("\t.chip_info = &%s_info_%s,\n" % (self.type_name, self.instance)) + file.write("\t.next = &%s,\n" % self.firstchilddevice().instance_name) + file.write("};\n") + return + + # Don't print duplicate devices, just print their children + if (self.dup): + return + + file.write("struct device %s = {\n" % self.instance_name) + file.write("\t.ops = 0,\n") + file.write("\t.bus = &%s.link[%d],\n" % \ + (self.firstparentdevice().instance_name, \ + self.firstparentdevicelink())) + file.write("\t.path = {%s},\n" % self.path) + file.write("\t.enabled = %d,\n" % self.enabled) + file.write("\t.on_mainboard = 1,\n") + if (self.resources): + file.write("\t.resources = %d,\n" % self.resources) + file.write("\t.resource = {%s\n\t },\n" % self.resource) + file.write("\t.link = {\n"); + links = 0 + bus = self + while(bus and (bus.path == self.path)): + child = bus.firstchilddevice() + if (child or (bus != self) or (bus.next_sibling and (bus.next_sibling.path == self.path))): + file.write("\t\t[%d] = {\n" % links) + file.write("\t\t\t.link = %d,\n" % links) + file.write("\t\t\t.dev = &%s,\n" % self.instance_name) + if (child): + file.write("\t\t\t.children = &%s,\n" %child.instance_name) + file.write("\t\t},\n") + links = links + 1 + if (1): + bus = bus.next_sibling + else: + bus = 0 + file.write("\t},\n") + file.write("\t.links = %d,\n" % (links)) + sibling = self.firstsiblingdevice(); + if (sibling): + file.write("\t.sibling = &%s,\n" % sibling.instance_name) + chip = self.firstparentchip() + if (chip and chip.chipconfig): + file.write("\t.chip_ops = &%s_ops,\n" % chip.type_name) + file.write("\t.chip_info = &%s_info_%s,\n" % (chip.type_name, chip.instance)) + if (self.next_device): + file.write("\t.next=&%s\n" % self.next_device.instance_name) file.write("};\n") - - def irq(self, irq): - self.irq = irq - + return + def addinit(self, code): + """Add init file to this part""" self.initcode.append(code) - def addregister(self, code): - code = dequote(code) - self.registercode.append(code) - + def addconfig(self, path): + """Add chip config file to this part""" + self.chipconfig = os.path.join(self.dir, path) + self.image.addconfiginclude(self.type_name, self.chipconfig) + + def addregister(self, field, value): + """Register static initialization information""" + if (self.chip_or_device != 'chip'): + fatal("Only chips can have register values") + field = dequote(field) + value = dequote(value) + setdict(self.registercode, field, value) + + def set_enabled(self, enabled): + self.enabled = enabled + + def start_resources(self): + self.resource = "" + self.resources = 0 + + def end_resources(self): + self.resource = "%s" % (self.resource) + + def add_resource(self, type, index, value): + """ Add a resource to a device """ + self.resource = "%s\n\t\t{ .flags=%s, .index=0x%x, .base=0x%x}," % (self.resource, type, index, value) + self.resources = self.resources + 1 + + def set_path(self, path): + self.path = path + if (self.prev_sibling and (self.prev_sibling.path == self.path)): + self.dup = 1 + if (self.prev_device): + self.prev_device.next_device = self.next_device + if (self.next_device): + self.next_device.prev_device = self.prev_device + if (self.image.last_device == self): + self.image.last_device = self.prev_device + self.prev_device = 0 + self.next_device = 0 + + def addpcipath(self, slot, function): + """ Add a relative pci style path from our parent to this device """ + if ((slot < 0) or (slot > 0x1f)): + fatal("Invalid device id") + if ((function < 0) or (function > 7)): + fatal("Invalid pci function %s" % function ) + self.set_path(".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}" % (slot, function)) + + def addpnppath(self, port, device): + """ Add a relative path to a pnp device hanging off our parent """ + if ((port < 0) or (port > 65536)): + fatal("Invalid port") + if ((device < 0) or (device > 0xffff)): + fatal("Invalid device") + self.set_path(".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}" % (port, device)) + + def addi2cpath(self, device): + """ Add a relative path to a i2c device hanging off our parent """ + if ((device < 0) or (device > 0x7f)): + fatal("Invalid device") + self.set_path(".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}" % (device)) + + def addapicpath(self, apic_id): + """ Add a relative path to a cpu device hanging off our parent """ + if ((apic_id < 0) or (apic_id > 255)): + fatal("Invalid device") + self.set_path(".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}" % (apic_id)) + + def addpci_domainpath(self, pci_domain): + """ Add a pci_domain number to a chip """ + if ((pci_domain < 0) or (pci_domain > 0xffff)): + fatal("Invalid pci_domain: 0x%x is out of the range 0 to 0xffff" % pci_domain) + self.set_path(".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}" % (pci_domain)) + + def addapic_clusterpath(self, cluster): + """ Add an apic cluster to a chip """ + if ((cluster < 0) or (cluster > 15)): + fatal("Invalid apic cluster: %d is out of the range 0 to ff" % cluster) + self.set_path(".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}" % (cluster)) + + def addcpupath(self, cpu_id): + """ Add a relative path to a cpu device hanging off our parent """ + if ((cpu_id < 0) or (cpu_id > 255)): + fatal("Invalid device") + self.set_path(".type=DEVICE_PATH_CPU,{.cpu={ .id = 0x%x }}" % (cpu_id)) + + + def addcpu_buspath(self, id): + """ Add a cpu_bus to a chip """ + if ((id < 0) or (id > 255)): + fatal("Invalid device") + self.set_path(".type=DEVICE_PATH_CPU_BUS,{.cpu_bus={ .id = 0x%x }}" % (id)) + def usesoption(self, name): + """Declare option that can be used by this part""" global global_options o = getdict(global_options, name) if (o == 0): - fatal("Error: can't use undefined option %s" % name) - o.setused() + fatal("can't use undefined option %s" % name) o1 = getdict(self.uses_options, name) if (o1): return setdict(self.uses_options, name, o) + exportoption(o, self.image.exported_options) # ----------------------------------------------------------------------------- # statements @@ -643,14 +1022,16 @@ class partobj: def getdict(dict, name): if name not in dict.keys(): - debug_print(1, "Undefined: %s" % name) + debug.info(debug.dict, "Undefined: %s" % name) return 0 v = dict.get(name, 0) - debug_print(1, "getdict %s returning %s" % (name, v)) + debug.info(debug.dict, "getdict %s returning %s" % (name, v)) return v def setdict(dict, name, value): - debug_print(1, "setdict sets %s to %s" % (name, value)) + debug.info(debug.dict, "setdict sets %s to %s" % (name, value)) + if name in dict.keys(): + print "Duplicate in dict: %s" % name dict[name] = value # options. @@ -667,68 +1048,137 @@ def newoption(name): global global_options, global_options_by_order o = getdict(global_options, name) if (o): - print "option %s already defined" % name - sys.exit(1) + fatal("option %s already defined" % name) o = option(name) setdict(global_options, name, o) global_options_by_order.append(name) -# option must be declared before being used in a part -# if we're not processing a part, then we must -# be at the top level where all options are available +def newoptionvalue(name, image): + g = getdict(global_option_values, name) + v = option_value(name, g) + if (image): + setdict(image.getvalues(), name, v) + else: + setdict(global_option_values, name, v) + return v + +def getoptionvalue(name, op, image): + global global_option_values + #print "getoptionvalue name %s op %s image %s\n" % (name, op,image) + if (op == 0): + # we want to debug config files, not the config tool, so no: + # print_stack() + fatal("Option %s undefined (missing use command?)" % name) + if (image): + v = getdict(image.getvalues(), name) + else: + v = getdict(global_option_values, name) + return v + def getoption(name, image): - global global_uses_options, global_option_values + """option must be declared before being used in a part + if we're not processing a part, then we must + be at the top level where all options are available""" + + global global_uses_options, alloptions, curimage + + #print "getoption: name %s image %s alloptions %s curimage %s\n\n" % (name, image, alloptions, curimage) curpart = partstack.tos() - if (curpart): - o = getdict(curpart.uses_options, name) - elif (alloptions): + if (alloptions): o = getdict(global_options, name) + elif (curpart): + o = getdict(curpart.uses_options, name) + if (o == 0): + print "curpart.uses_options is %s\n" % curpart.uses_options else: o = getdict(global_uses_options, name) - if (o == 0 or not o.defined): - error("Option %s undefined (missing use command?)" % name) - return - v = 0 - if (image): - v = o.getvalue(image, image.getvalues()) + v = getoptionvalue(name, o, image) + if (v == 0): + v = getoptionvalue(name, o, 0) if (v == 0): - v = o.getvalue(image, global_option_values) - return v.contents() + fatal("No value for option %s" % name) + val = v.contents() + if (not (type(val) is types.StringType)): + return v.contents() + if (val == '' or val[0] != '{'): + return v.contents() + s = curimage + curimage = image + val = parse('delexpr', val) + curimage = s + exitiferrors() + return val + +def setoption(name, value, imp): + """Set an option from within a configuration file. Normally this + is only permitted in the target (top level) configuration file. + If 'imp' is true, then set an option implicitly (e.g. 'arch' + and 'mainboard' statements). Implicit options can be set anywhere + the statements are legal, but also performs an implicit 'uses' + for the option""" -def setoption(name, value): global loc, global_options, global_option_values, curimage + curpart = partstack.tos() - if (curpart and curpart.type != 'mainboard'): - fatal("Options may only be set in top-level and mainboard configuration files") - o = getdict(global_options, name) - if (o == 0): - fatal("Attempt to set nonexistent option %s" % name) - v = option_value(value) - if (curimage): - o.setvalue(v, curimage.getvalues(), loc) + if (not imp and curpart): + fatal("Options may only be set in target configuration file") + if (imp): + usesoption(name) + if (curpart): + o = getdict(curpart.uses_options, name) else: - o.setvalue(v, global_option_values, loc) - -def setdefault(name, value): - global loc, global_options - o = getdict(global_options, name) + o = getdict(global_uses_options, name) if (not o): + fatal("Attempt to set nonexistent option %s (missing USES?)" % name) + v = getoptionvalue(name, o, curimage) + if (v == 0): + v = newoptionvalue(name, curimage) + v.setvalue(value) + +def exportoption(op, exported_options): + if (not op.isexportable()): return - if (o.default): - print "setdefault: attempt to duplicate default for %s" % name - return - v = option_value(value) - o.setdefault(v, loc) + if (not op in exported_options): + exported_options.append(op) + +def setdefault(name, value, isdef): + """Set the default value of an option from within a configuration + file. This is permitted from any configuration file, but will + result in a warning if the default is set more than once. + If 'isdef' is set, we're defining the option in Options.lb so + there is no need for 'uses'.""" + + global loc, global_options, curimage + + if (isdef): + o = getdict(global_options, name) + if (not o): + return + image = 0 + else: + curpart = partstack.tos() + if (curpart): + o = getdict(curpart.uses_options, name) + else: + o = getdict(global_uses_options, name) + if (not o): + fatal("Attempt to set default for nonexistent option %s (missing USES?)" % name) + image = curimage + + v = getoptionvalue(name, o, image) + if (v == 0): + v = newoptionvalue(name, image) + v.setdefault(value) def setnodefault(name): global loc, global_options o = getdict(global_options, name) if (not o): return - if (o.default): - print "setdefault: attempt to duplicate default for %s" % name - return - o.setnodefault(loc) + v = getdict(global_option_values, name) + if (v != 0): + warning("removing default for %s" % name) + del global_option_values[name] def setcomment(name, value): global loc, global_options @@ -742,7 +1192,8 @@ def setexported(name): o = getdict(global_options, name) if (not o): fatal("setexported: %s not here" % name) - o.setexported() + o.setexportable() + global_exported_options.append(o) def setnoexport(name): global global_options @@ -750,6 +1201,8 @@ def setnoexport(name): if (not o): fatal("setnoexport: %s not here" % name) o.setnoexport() + if (o in global_exported_options): + global_exported_options.remove(o) def setexportable(name): global global_options @@ -768,52 +1221,43 @@ def setformat(name, fmt): def getformated(name, image): global global_options, global_option_values o = getdict(global_options, name) - if (o == 0 or not o.defined): - fatal( "Option %s undefined." % name) - v = 0 - if (image): - v = o.getvalue(image, image.getvalues()) - if (v == 0): - v = o.getvalue(image, global_option_values) + v = getoption(name, image) f = o.getformat() - return (f % v.contents()) + return (f % v) -def isexported(name): +def setwrite(name, part): global global_options o = getdict(global_options, name) - if (o): - return o.isexported() - return 0 - -#def isdefined(name, part): -# global global_options -# if (part): -# o = getdict(part.uses_options, name) -# else: -# o = getdict(global_options, name) -# if (o): -# return o.isdefined() -# return 0 + if (not o): + fatal("setwrite: %s not here" % name) + o.setwrite(part) + +def hasvalue(name, image): + global global_options + o = getdict(global_options, name) + if (o == 0): + return 0 + v = 0 + if (image): + v = getdict(image.getvalues(), name) + if (v == 0): + v = getdict(global_option_values, name) + return (v != 0) def isset(name, part): - global global_uses_options + global global_uses_options, global_option_values, curimage if (part): o = getdict(part.uses_options, name) else: o = getdict(global_uses_options, name) - if (o): - return o.isset() - return 0 - -#def isused(name, part): -# global global_options -# if (part): -# o = getdict(part.uses_options, name) -# else: -# o = getdict(global_options, name) -# if (o): -# return o.isused() -# return 0 + if (o == 0): + return 0 + v = 0 + if (curimage): + v = getdict(curimage.getvalues(), name) + if (v == 0): + v = getdict(global_option_values, name) + return (v != 0 and v.isset()) def usesoption(name): global global_options, global_uses_options @@ -824,11 +1268,11 @@ def usesoption(name): o = getdict(global_options, name) if (o == 0): fatal("Can't use undefined option %s" % name) - o.setused() o1 = getdict(global_uses_options, name) if (o1): return setdict(global_uses_options, name, o) + exportoption(o, global_exported_options) def validdef(name, defval): global global_options @@ -842,11 +1286,12 @@ def validdef(name, defval): if ((defval & 4) != 4): fatal("Must specify comment for option %s" % name) -def loadoptions(): - file = os.path.join('src', 'config', 'Options.lb') +def loadoptions(path, file, rule): + file = os.path.join('src', path, file) optionsfile = os.path.join(treetop, file) + fp = safe_open(optionsfile, 'r') loc.push(file) - if (not parse('options', open(optionsfile, 'r').read())): + if (not parse(rule, fp.read())): fatal("Could not parse file") loc.pop() @@ -858,15 +1303,20 @@ def addinit(path): curimage.setinitfile(dirstack.tos() + '/' + path) print "Adding init file: %s" % path -def addregister(code): +def addconfig(path): + global partstack + curpart = partstack.tos() + curpart.addconfig(path) + +def addregister(field, value): global partstack curpart = partstack.tos() - curpart.addregister(code) + curpart.addregister(field, value) -# we do the crt0include as a dictionary, so that if needed we -# can trace who added what when. Also it makes the keys -# nice and unique. def addcrt0include(path): + """we do the crt0include as a dictionary, so that if needed we + can trace who added what when. Also it makes the keys + nice and unique.""" global curimage curimage.addinitinclude(0, path) @@ -881,20 +1331,19 @@ def addldscript(path): fullpath = treetop + '/src/' + path else: fullpath = curdir + '/' + path - debug_print(1, "fullpath :%s: curdir :%s: path :%s:" % (fullpath, curdir, path)) + debug.info(debug.statement, "fullpath :%s: curdir :%s: path :%s:" % (fullpath, curdir, path)) curimage.addldscript(fullpath) def payload(path): global curimage curimage.setpayload(path) -# adduserdefine("PAYLOAD:=%s"%path) -# addrule('payload') -# adddep('payload', path) -# addaction('payload', 'cp $< $@') + adduserdefine("PAYLOAD:=%s"%path) def startromimage(name): global romimages, curimage, target_dir, target_name - print "Configuring ROMIMAGE %s" % name + curpart = partstack.tos() + print "Configuring ROMIMAGE %s Curimage %s" % (name, curimage) + print "Curpart is %s\n" % curpart o = getdict(romimages, name) if (o): fatal("romimage %s previously defined" % name) @@ -903,29 +1352,55 @@ def startromimage(name): #o = partobj(curimage, target_dir, 0, 'board', target_name) #curimage.setroot(o) setdict(romimages, name, curimage) + dodir('/config', 'Config.lb') def endromimage(): global curimage + global bootblocksize + mainboard() + imagesize = getoption("ROM_IMAGE_SIZE", curimage) + bootblocksize += imagesize print "End ROMIMAGE" curimage = 0 #curpart = 0 -def mainboard(path): - full_path = os.path.join(treetop, 'src', 'mainboard', path) - setoption('MAINBOARD', full_path) - vendor = re.sub("/.*", "", path) +def mainboardsetup(path): + global full_mainboard_path, mainboard_path + mainboard_path = os.path.join('mainboard', path) + loadoptions(mainboard_path, 'Options.lb', 'mainboardvariables') + full_mainboard_path = os.path.join(treetop, 'src', 'mainboard', path) + vendor = re.sub("/.*", "", path) part_number = re.sub("[^/]*/", "", path) - setoption('MAINBOARD_VENDOR', vendor) - setoption('MAINBOARD_PART_NUMBER', part_number) - dodir('/config', 'Config.lb') - part('mainboard', path, 'Config.lb') + setdefault('MAINBOARD', full_mainboard_path, 0) + setdefault('MAINBOARD_VENDOR', vendor, 0) + setdefault('MAINBOARD_PART_NUMBER', part_number, 0) + +def mainboard(): + global curimage, dirstack, partstack + file = 'Config.lb' + partdir = mainboard_path + srcdir = os.path.join(treetop, 'src') + fulldir = os.path.join(srcdir, partdir) + type_name = flatten_name(partdir) + newpart = partobj(curimage, fulldir, partstack.tos(), 'mainboard', \ + 'mainboard', 0, 'chip') + #print "Configuring PART %s" % (type) + partstack.push(newpart) + #print " new PART tos is now %s\n" %partstack.tos().info() + dirstack.push(fulldir) + loadoptions(mainboard_path, 'Options.lb', 'mainboardvariables') + # special case for 'cpu' parts. + # we could add a new function too, but this is rather trivial. + # if the part is a cpu, and we haven't seen it before, + # arrange to source the directory /cpu/'type' + doconfigfile(srcdir, partdir, file, 'cfgfile') curimage.setroot(partstack.tos()) partpop() -def addbuildrom(size, roms): +def addbuildrom(filename, size, roms): global buildroms print "Build ROM size %d" % size - b = buildrom(size, roms) + b = buildrom(filename, size, roms) buildroms.append(b) def addinitobject(object_name): @@ -940,6 +1415,10 @@ def adddriver(driver_name): global curimage curimage.adddriverrule(driver_name) +def addsmmobject(object_name): + global curimage + curimage.addsmmobjectrule(object_name) + def target(name): global target_dir, target_name print "Configuring TARGET %s" % name @@ -951,31 +1430,61 @@ def target(name): print "Will place Makefile, crt0.S, etc. in %s" % target_dir -def part(name, path, file): +def cpudir(path): + global cpu_type + if (cpu_type and (cpu_type != path)): + fatal("Two different CPU types: %s and %s" % (cpu_type, path)) + srcdir = "/cpu/%s" % path + dodir(srcdir, "Config.lb") + cpu_type = path + +def devicepart(type): + global curimage, dirstack, partstack + newpart = partobj(curimage, 0, partstack.tos(), type, \ + '', 0, 'device') + #print "Configuring PART %s" % (type) + partstack.push(newpart) + #print " new PART tos is now %s\n" %partstack.tos().info() + # just push TOS, so that we can pop later. + dirstack.push(dirstack.tos()) + +def part(type, path, file, name): global curimage, dirstack, partstack - partdir = os.path.join(name, path) + partdir = os.path.join(type, path) srcdir = os.path.join(treetop, 'src') fulldir = os.path.join(srcdir, partdir) - newpart = partobj(curimage, fulldir, partstack.tos(), name, path) - print "Configuring PART %s, path %s" % (name, path) + type_name = flatten_name(partdir) + newpart = partobj(curimage, fulldir, partstack.tos(), type, \ + type_name, name, 'chip') + #print "Configuring PART %s, path %s" % (type, path) partstack.push(newpart) + #print " new PART tos is now %s\n" %partstack.tos().info() dirstack.push(fulldir) - doconfigfile(srcdir, partdir, file) + # special case for 'cpu' parts. + # we could add a new function too, but this is rather trivial. + # if the part is a cpu, and we haven't seen it before, + # arrange to source the directory /cpu/'type' + if (type == 'cpu'): + cpudir(path) + else: + doconfigfile(srcdir, partdir, file, 'cfgfile') def partpop(): global dirstack, partstack - curpart = partstack.pop() + curpart = partstack.tos() if (curpart == 0): fatal("Trying to pop non-existent part") - print "End PART %s" % curpart.type + #print "End PART %s" % curpart.part # Warn if options are used without being set in this part - for i in curpart.uses_options.keys(): - if (not isset(i, curpart)): - print "WARNING: Option %s using default value %s" % (i, getformated(i, curpart.image)) + for op in curpart.uses_options.keys(): + if (not isset(op, curpart)): + notice("Option %s using default value %s" % (op, getformated(op, curpart.image))) + oldpart = partstack.pop() dirstack.pop() + #print "partstack.pop, TOS is now %s\n" % oldpart.info() -# dodir is like part but there is no new part def dodir(path, file): + """dodir is like part but there is no new part""" global dirstack # if the first char is '/', it is relative to treetop, # else relative to curdir @@ -986,16 +1495,14 @@ def dodir(path, file): path = re.sub('^/*', '', path) else: fullpath = dirstack.tos() - debug_print(1, "DODIR: path %s, fullpath %s" % (path, fullpath)) + debug.info(debug.statement, "DODIR: path %s, fullpath %s" % (path, fullpath)) dirstack.push(os.path.join(fullpath, path)) - doconfigfile(fullpath, path, file) + doconfigfile(fullpath, path, file, 'cfgfile') dirstack.pop() def lookup(name): global curimage - v = getoption(name, curimage) - exitiferrors() - return v + return getoption(name, curimage) def addrule(id): global curimage @@ -1013,18 +1520,20 @@ def adddep(id, str): global curimage curimage.addmakedepend(id, str) -# arch is 'different' ... darn it. -def set_arch(my_arch): +def setarch(my_arch): + """arch is 'different' ... darn it.""" global curimage + print "SETTING ARCH %s\n" % my_arch curimage.setarch(my_arch) - setoption('ARCH', my_arch) - part('arch', my_arch, 'Config.lb') + setdefault('ARCH', my_arch, 1) + part('arch', my_arch, 'Config.lb', 0) -def doconfigfile(path, confdir, file): +def doconfigfile(path, confdir, file, rule): rname = os.path.join(confdir, file) loc.push(rname) fullpath = os.path.join(path, rname) - if (not parse('cfgfile', open(fullpath, 'r').read())): + fp = safe_open(fullpath, 'r') + if (not parse(rule, fp.read())): fatal("Could not parse file") exitiferrors() loc.pop() @@ -1033,23 +1542,23 @@ def doconfigfile(path, confdir, file): # MISC FUNCTIONS #============================================================================= def ternary(val, yes, no): - debug_print(1, "ternary %s" % expr) - debug_print(1, "expr %s a %d yes %d no %d"% (expr, a, yes, no)) + debug.info(debug.statement, "ternary %s" % expr) + debug.info(debug.statement, "expr %s a %d yes %d no %d"% (expr, a, yes, no)) if (val == 0): - debug_print("Ternary returns %d" % yes) + debug.info(debug.statement, "Ternary returns %d" % yes) return yes else: - debug_print("Ternary returns %d" % no) + debug.info(debug.statement, "Ternary returns %d" % no) return no -# atoi is in the python library, but not strtol? Weird! def tohex(name): + """atoi is in the python library, but not strtol? Weird!""" return eval('int(%s)' % name) -def IsInt( str ): +def IsInt(str): """ Is the given string an integer?""" try: - num = int(str) + num = long(str) return 1 except ValueError: return 0 @@ -1062,11 +1571,12 @@ def dequote(str): return a def flatten_name(str): - a = re.sub("/", "_", str) + a = re.sub("[/-]", "_", str) return a -# If the first part of matches treetop, replace that part with "$(TOP)" def topify(path): + """If the first part of matches treetop, replace + that part with $(TOP)""" if path[0:len(treetop)] == treetop: path = path[len(treetop):len(path)] if (path[0:1] == "/"): @@ -1092,12 +1602,17 @@ parser Config: token ARCH: 'arch' token BUILDROM: 'buildrom' token COMMENT: 'comment' + token CONFIG: 'config' token CPU: 'cpu' + token CPU_BUS: 'cpu_bus' + token CHIP: 'chip' token DEFAULT: 'default' token DEFINE: 'define' token DEPENDS: 'depends' + token DEVICE: 'device' token DIR: 'dir' token DRIVER: 'driver' + token DRQ: 'drq' token ELSE: 'else' token END: 'end' token EOF: '$' @@ -1108,12 +1623,15 @@ parser Config: token INIT: 'init' token INITOBJECT: 'initobject' token INITINCLUDE: 'initinclude' + token IO: 'io' + token IRQ: 'irq' token LDSCRIPT: 'ldscript' token LOADOPTIONS: 'loadoptions' token MAINBOARD: 'mainboard' token MAINBOARDINIT: 'mainboardinit' token MAKEDEFINE: 'makedefine' token MAKERULE: 'makerule' + token MEM: 'mem' token NEVER: 'never' token NONE: 'none' token NORTHBRIDGE: 'northbridge' @@ -1124,23 +1642,38 @@ parser Config: token PRINT: 'print' token REGISTER: 'register' token ROMIMAGE: 'romimage' + token SMMOBJECT: 'smmobject' token SOUTHBRIDGE: 'southbridge' token SUPERIO: 'superio' token TARGET: 'target' token USED: 'used' token USES: 'uses' - token NUM: r'[0-9]+' - token XNUM: r'0x[0-9a-fA-F]+' + token WRITE: 'write' + token NUM: '[0-9]+' + token HEX_NUM: '[0-9a-fA-F]+' + token HEX_PREFIX: '0x' # Why is path separate? Because paths to resources have to at least # have a slash, we thinks - token PATH: r'[a-zA-Z0-9_.][a-zA-Z0-9/_.]+[a-zA-Z0-9_.]+' + token PATH: r'[-a-zA-Z0-9_.][-a-zA-Z0-9/_.]+[-a-zA-Z0-9_.]+' # Dir's on the other hand are abitrary # this may all be stupid. + token RULE: r'[-a-zA-Z0-9_$()./]+[-a-zA-Z0-9_ $()./]+[-a-zA-Z0-9_$()./]+' token DIRPATH: r'[-a-zA-Z0-9_$()./]+' token ID: r'[a-zA-Z_.]+[a-zA-Z0-9_.]*' token DELEXPR: r'{([^}]+|\\.)*}' token STR: r'"([^\\"]+|\\.)*"' token RAWTEXT: r'.*' + token ON: 'on' + token OFF: 'off' + token PCI: 'pci' + token PNP: 'pnp' + token I2C: 'i2c' + token APIC: 'apic' + token APIC_CLUSTER: 'apic_cluster' + token CPU: 'cpu' + token CPU_BUS: 'cpu_bus' + token PCI_DOMAIN: 'pci_domain' + rule expr: logical {{ l = logical }} ( "&&" logical {{ l = l and logical }} @@ -1160,8 +1693,8 @@ parser Config: )* {{ return v }} # A term is a number, variable, or an expression surrounded by parentheses - rule term: NUM {{ return atoi(NUM) }} - | XNUM {{ return tohex(XNUM) }} + rule term: NUM {{ return long(NUM, 10) }} + | HEX_PREFIX HEX_NUM {{ return long(HEX_NUM, 16) }} | ID {{ return lookup(ID) }} | unop {{ return unop }} | "\\(" expr "\\)" {{ return expr }} @@ -1170,26 +1703,31 @@ parser Config: rule partend<>: (stmt<>)* END {{ if (C): partpop()}} - rule northbridge<>: - NORTHBRIDGE PATH {{ if (C): part('northbridge', PATH, 'Config.lb') }} - partend<> - - rule superio<>: SUPERIO PATH {{ if (C): part('superio', PATH, 'Config.lb') }} - partend<> - - rule cpu<>: CPU ID {{ if (C): part('cpu', ID, 'Config.lb') }} - partend<> - - rule pmc<>: PMC PATH {{ if (C): part('pmc', PATH, 'Config.lb') }} - partend<> + # This is needed because the legacy cpu command could not distinguish + # between cpu vendors. It should just be PATH, but getting this change + # into the source tree will be tricky... + # DO NOT USE ID AS IT MAY GO AWAY IN THE FUTURE + rule partid: ID {{ return ID }} + | PATH {{ return PATH }} + +# rule parttype: NORTHBRIDGE {{ return 'northbridge' }} +# | SUPERIO {{ return 'superio' }} +# | PMC {{ return 'pmc' }} +# | SOUTHBRIDGE {{ return 'southbridge' }} +# | CPU {{ return 'cpu' }} +# | CHIP {{ return '' }} +# + rule parttype: CHIP {{ return '' }} - rule arch<>: ARCH ID {{ if (C): set_arch(ID) }} - partend<> + rule partdef<>: {{ name = 0 }} + parttype partid + [ STR {{ name = dequote(STR) }} + ] {{ if (C): part(parttype, partid, 'Config.lb', name) }} + partend<> - rule southbridge<>: - SOUTHBRIDGE PATH {{ if (C): part('southbridge', PATH, 'Config.lb')}} + rule arch<>: ARCH ID {{ if (C): setarch(ID) }} partend<> - + rule mainboardinit<>: MAINBOARDINIT DIRPATH {{ if (C): addcrt0include(DIRPATH)}} @@ -1205,8 +1743,14 @@ parser Config: rule driver<>: DRIVER DIRPATH {{ if (C): adddriver(DIRPATH)}} + rule smmobject<>: + SMMOBJECT DIRPATH {{ if (C): addsmmobject(DIRPATH)}} + + rule dir<>: DIR DIRPATH {{ if (C): dodir(DIRPATH, 'Config.lb') }} + rule default<>: DEFAULT ID EQ value {{ if (C): setdefault(ID, value, 0) }} + rule ldscript<>: LDSCRIPT DIRPATH {{ if (C): addldscript(DIRPATH) }} rule iif<>: IF ID {{ c = lookup(ID) }} @@ -1214,13 +1758,10 @@ parser Config: [ ELSE (stmt<>)* ] END - rule depsacts<>: - ( DEPENDS STR {{ if (C): adddep(ID, STR) }} - | ACTION STR {{ if (C): addaction(ID, STR) }} + rule makerule<>: MAKERULE RULE {{ if (C): addrule(RULE) }} + ( DEPENDS STR {{ if (C): adddep(RULE, STR) }} + | ACTION STR {{ if (C): addaction(RULE, STR) }} )* - - rule makerule<>: MAKERULE DIRPATH {{ if (C): addrule(DIRPATH) }} - depsacts<> END rule makedefine<>: @@ -1231,8 +1772,76 @@ parser Config: rule init<>: INIT DIRPATH {{ if (C): addinit(DIRPATH) }} - rule register<>: REGISTER STR {{ if (C): addregister(STR) }} - + rule field: STR {{ return STR }} + + rule register<>: REGISTER field '=' STR {{ if (C): addregister(field, STR) }} + + rule enable<>: {{ val = 1 }} + ( ON {{ val = 1 }} + | OFF {{ val = 0 }} + ) {{ if(C): partstack.tos().set_enabled(val) }} + + rule resource<>: {{ type = "" }} + ( IO {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IO" }} + | MEM {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_MEM" }} + | IRQ {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IRQ" }} + | DRQ {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_DRQ" }} + ) + term '=' {{ index = term }} + term {{ value = term }} + {{ if (C): partstack.tos().add_resource(type, index, value) }} + + + rule resources<>: {{ if (C): partstack.tos().start_resources() }} + ( resource<> )* + {{ if (C): partstack.tos().end_resources() }} + + + rule pci<>: PCI {{ if (C): devicepart('pci') }} + + HEX_NUM {{ slot = int(HEX_NUM,16) }} + '.' HEX_NUM {{ function = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addpcipath(slot, function) }} + rule pci_domain<>: + PCI_DOMAIN {{ if (C): devicepart('pci_domain') }} + HEX_NUM {{ pci_domain = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addpci_domainpath(pci_domain) }} + + rule pnp<>: PNP {{ if (C): devicepart('pnp') }} + HEX_NUM {{ port = int(HEX_NUM,16) }} + '.' HEX_NUM {{ device = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addpnppath(port, device) }} + + rule i2c<>: I2C {{ if (C): devicepart('i2c') }} + HEX_NUM {{ device = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addi2cpath(device) }} + + rule apic<>: APIC {{ if (C): devicepart('apic') }} + HEX_NUM {{ apic_id = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addapicpath(apic_id) }} + + rule apic_cluster<>: APIC_CLUSTER {{ if (C): devicepart('apic_cluster') }} + HEX_NUM {{ cluster = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addapic_clusterpath(cluster) }} + + rule cpu<>: CPU {{ if (C): devicepart('cpu') }} + HEX_NUM {{ id = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addcpupath(id) }} + + rule cpu_bus<>: CPU_BUS {{ if (C): devicepart('cpu_bus') }} + HEX_NUM {{ id = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addcpu_buspath(id) }} + + rule dev_path<>: + pci<> {{ return pci }} + | pci_domain<> {{ return pci_domain }} + | pnp<> {{ return pnp }} + | i2c<> {{ return i2c }} + | apic<> {{ return apic }} + | apic_cluster<> {{ return apic_cluster }} + | cpu<> {{ return cpu }} + | cpu_bus<> {{ return cpu_bus }} + rule prtval: expr {{ return str(expr) }} | STR {{ return STR }} @@ -1244,9 +1853,17 @@ parser Config: [ "," prtlist {{ val = val + prtlist }} ] {{ if (C): print eval(val) }} + rule config<>: CONFIG PATH {{ if (C): addconfig(PATH) }} + + rule device<>: DEVICE dev_path<> + enable<> + resources<> + partend<> + rule stmt<>: arch<> {{ return arch}} | addaction<> {{ return addaction }} - | cpu<> {{ return cpu}} + | config<> {{ return config}} + | default<> {{ return default}} | dir<> {{ return dir}} | driver<> {{ return driver }} | iif<> {{ return iif }} @@ -1257,29 +1874,37 @@ parser Config: | mainboardinit<> {{ return mainboardinit }} | makedefine<> {{ return makedefine }} | makerule<> {{ return makerule }} - | northbridge<> {{ return northbridge }} | object<> {{ return object }} | option<> {{ return option }} - | pmc<> {{ return pmc}} - | prtstmt<> {{ return prtstmt}} - | register<> {{ return register}} - | southbridge<> {{ return southbridge }} - | superio<> {{ return superio }} + | partdef<> {{ return partdef }} + | prtstmt<> {{ return prtstmt }} + | register<> {{ return register }} + | device<> {{ return device }} + | smmobject<> {{ return smmobject }} # ENTRY for parsing Config.lb file rule cfgfile: (uses<<1>>)* (stmt<<1>>)* EOF {{ return 1 }} + rule cfgfile: (uses<<1>>)* + (stmt<<1>>)* + EOF {{ return 1 }} + rule usesid<>: ID {{ if (C): usesoption(ID) }} rule uses<>: USES (usesid<>)+ + rule mainboardvariables: (uses<<1>>)* + (default<<1>>)* + (option<<1>>)* + END {{ return 1}} + rule value: STR {{ return dequote(STR) }} | expr {{ return expr }} | DELEXPR {{ return DELEXPR }} - rule option<>: OPTION ID EQ value {{ if (C): setoption(ID, value) }} + rule option<>: OPTION ID EQ value {{ if (C): setoption(ID, value, 0) }} rule opif<>: IF ID {{ c = lookup(ID) }} (opstmt<>)* @@ -1292,8 +1917,8 @@ parser Config: rule payload<>: PAYLOAD DIRPATH {{ if (C): payload(DIRPATH) }} - rule mainboard<>: - MAINBOARD PATH {{ if (C): mainboard(PATH) }} + rule mainboard: + MAINBOARD PATH {{ mainboardsetup(PATH) }} rule romif<>: IF ID {{ c = lookup(ID) }} (romstmt<>)* @@ -1302,36 +1927,37 @@ parser Config: rule romstmt<>: romif<> | option<> - | mainboard<> | payload<> rule romimage: ROMIMAGE STR {{ startromimage(dequote(STR)) }} (romstmt<<1>>)* END {{ endromimage() }} - rule roms: STR {{ s = '(' + STR }} + rule roms: STR {{ s = '[' + STR }} ( STR {{ s = s + "," + STR }} - )* {{ return eval(s + ')') }} + )* {{ return eval(s + ']') }} - rule buildrom: BUILDROM expr roms {{ addbuildrom(expr, roms) }} + rule buildrom: BUILDROM DIRPATH expr roms {{ addbuildrom(DIRPATH, expr, roms) }} rule romstmts: romimage | buildrom | opstmt<<1>> # ENTRY for parsing root part - rule board: LOADOPTIONS {{ loadoptions() }} + rule board: {{ loadoptions("config", "Options.lb", "options") }} TARGET DIRPATH {{ target(DIRPATH) }} - (uses<<1>>)* + mainboard (romstmts)* EOF {{ return 1 }} # ENTRY for parsing a delayed value rule delexpr: "{" expr "}" EOF {{ return expr }} + rule wrstr<>: STR {{ setwrite(ID, dequote(STR)) }} + rule defstmts<>: {{ d = 0 }} ( DEFAULT - ( value {{ setdefault(ID, value) }} + ( value {{ setdefault(ID, value, 1) }} | NONE {{ setnodefault(ID) }} ) {{ d = d | 1 }} | FORMAT STR {{ setformat(ID, dequote(STR)) }} @@ -1341,6 +1967,7 @@ parser Config: | NEVER {{ setnoexport(ID) }} ) {{ d = d | 2 }} | COMMENT STR {{ setcomment(ID, dequote(STR)); d = d | 4 }} + | WRITE (wrstr<>)+ )+ {{ return d }} rule define: DEFINE ID {{ newoption(ID) }} @@ -1354,55 +1981,60 @@ parser Config: # FILE OUTPUT #============================================================================= def writemakefileheader(file, fname): - file.write("# File: %s\n" % fname) - file.write("# This file was generated by '%s %s %s'\n\n" - % (sys.argv[0], sys.argv[1], sys.argv[2])) + file.write("# File: %s is autogenerated\n" % fname) + +def writemakefilefooter(file, fname): + file.write("\n\n%s: %s %s\n" + % (os.path.basename(fname), os.path.abspath(sys.argv[0]), top_config_file)) + file.write("\t(cd %s ; export PYTHONPATH=%s/util/newconfig ; python %s %s %s)\n\n" + % (os.getcwd(), treetop, sys.argv[0], sys.argv[1], sys.argv[2])) def writemakefilesettings(path): + """ Write Makefile.settings to seperate the settings + from the actual makefile creation.""" + global treetop, target_dir - # Write Makefile.settings to seperate the settings - # from the actual makefile creation - # In practice you need to rerun NLBConfig.py to change - # these but in theory you shouldn't need to. filename = os.path.join(path, "Makefile.settings") print "Creating", filename - file = open(filename, 'w+') + file = safe_open(filename, 'w+') writemakefileheader(file, filename) file.write("TOP:=%s\n" % (treetop)) file.write("TARGET_DIR:=%s\n" % target_dir) -# for i in global_options_by_order: -# if (isexported(i, 0)): -# file.write("export %s:=%s\n" % (i, getformated(i, 0))) -# file.write("export VARIABLES := ") -# for i in global_options.keys(): -# if (isexported(i, 0)): -# file.write("%s " % i) - file.write("\n") + writemakefilefooter(file, filename) file.close() def writeimagesettings(image): + """Write Makefile.settings to seperate the settings + from the actual makefile creation.""" + global treetop global global_options_by_order - # Write Makefile.settings to seperate the settings - # from the actual makefile creation - # In practice you need to rerun NLBConfig.py to change - # these but in theory you shouldn't need to. filename = os.path.join(image.gettargetdir(), "Makefile.settings") print "Creating", filename - file = open(filename, 'w+') + file = safe_open(filename, 'w+') writemakefileheader(file, filename) file.write("TOP:=%s\n" % (treetop)) file.write("TARGET_DIR:=%s\n" % (image.gettargetdir())) - for i in global_options_by_order: - if (isexported(i)): - file.write("export %s:=%s\n" % (i, getformated(i, image))) - file.write("export VARIABLES := ") - for i in global_options_by_order: - if (isexported(i)): - file.write("%s " % i) file.write("\n") + exported = [] + for o in global_exported_options: + exported.append(o) + for o in image.exported_options: + if (not o in exported): + exported.append(o) + for o in exported: + file.write("export %s:=" % o.name) + if (hasvalue(o.name, image)): + file.write("%s" % getformated(o.name, image)) + file.write("\n") + file.write("\n") + file.write("export VARIABLES :=\n") + for o in exported: + file.write("export VARIABLES += %s\n" % o.name) + file.write("\n") + # writemakefilefooter(file,filename) file.close() # write the romimage makefile @@ -1412,26 +2044,27 @@ def writeimagesettings(image): def writeimagemakefile(image): makefilepath = os.path.join(image.gettargetdir(), "Makefile") print "Creating", makefilepath - file = open(makefilepath, 'w+') + file = safe_open(makefilepath, 'w+') writemakefileheader(file, makefilepath) + # main rule + file.write("\nall: coreboot.rom\n\n") + file.write(".PHONY: all\n\n") #file.write("include cpuflags\n") # Putting "include cpuflags" in the Makefile has the problem that the # cpuflags file would be generated _after_ we want to include it. # Instead, let make do the work of computing CPUFLAGS: file.write("# Get the value of TOP, VARIABLES, and several other variables.\n") file.write("include Makefile.settings\n\n") - file.write("# Function to create an item like -Di586 or -DMAX_CPUS='1' or -Ui686\n") - file.write("D_item = $(if $(subst undefined,,$(origin $1)),-D$1$(if $($1),='$($1)',),-U$1)\n\n") + file.write("# Function to create an item like -Di586 or -DCONFIG_MAX_CPUS='1' or -Ui686\n") + file.write("D_item = $(shell echo '$(if $(subst undefined,,$(origin $1)),\\#define $1$(if $($1), $($1),),\\#undef $1)' >> settings.h)\n\n") file.write("# Compute the value of CPUFLAGS here during make's first pass.\n") - file.write("CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))\n\n") + file.write("CPUFLAGS := $(strip $(shell echo '/* autogenerated */' > settings.h)$(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))--include=settings.h)\n\n") for i in image.getuserdefines(): file.write("%s\n" %i) file.write("\n") - # main rule - file.write("all: linuxbios.rom") # print out all the object dependencies file.write("\n# object dependencies (objectrules:)\n") file.write("INIT-OBJECTS :=\n") @@ -1447,9 +2080,20 @@ def writeimagemakefile(image): for objrule, obj in image.getobjectrules().items(): obj_name = obj[0] obj_source = obj[1] - file.write("OBJECTS-1 += %s\n" % (obj_name)) + file.write("OBJECTS += %s\n" % (obj_name)) file.write("SOURCES += %s\n" % (obj_source)) + for srule, smm in image.getsmmobjectrules().items(): + s_name = smm[0] + s_source = smm[1] + file.write("SMM-OBJECTS += %s\n" % (s_name)) + file.write("SOURCES += %s\n" % (s_source)) + + + # for chip_target.c + file.write("OBJECTS += static.o\n") + file.write("SOURCES += static.c\n") + for driverrule, driver in image.getdriverrules().items(): obj_name = driver[0] obj_source = driver[1] @@ -1465,7 +2109,7 @@ def writeimagemakefile(image): # Print out the dependencies for crt0_includes.h file.write("\n# Dependencies for crt0_includes.h\n") file.write("CRT0_INCLUDES:=\n") - for inc in image.getinitincludes().keys(): + for inc in image.getinitincludes(): if (local_path.match(inc)): file.write("CRT0_INCLUDES += %s\n" % inc) else: @@ -1473,26 +2117,47 @@ def writeimagemakefile(image): # Print out the user defines. file.write("\n# userdefines:\n") - #for udef in image.userdefines: - #file.write("%s\n" % udef) # Print out the base rules. # Need to have a rule that counts on 'all'. file.write("\n# mainrulelist:") - #file.write("\nmainrule: %s\n" % image.mainrulelist) # Print out any user rules. file.write("\n# From makerule or docipl commands:\n") - # Old way (hash order): for target in makebaserules.keys(): - # New way (config file order): - #for target in image.makerule_targets: - #image.makebaserules[target].write(file) + + file.write("\n# initobjectrules:\n") + for irule, init in image.getinitobjectrules().items(): + source = topify(init[1]) + type = init[2] + if (type == 'S'): + # for .S, .o depends on .s + file.write("%s: %s.s\n" % (init[0], init[3])) + file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n") + # and .s depends on .S + file.write("%s.s: %s\n" % (init[3], source)) + # Note: next 2 lines are ONE output line! + file.write("\t$(CPP) $(CPPFLAGS) $< ") + file.write(">$@.new && mv $@.new $@\n") + else: + file.write("%s: %s\n" % (init[0], source)) + file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n") file.write("\n# objectrules:\n") for objrule, obj in image.getobjectrules().items(): source = topify(obj[1]) - file.write("%s: %s\n" % (obj[0], source)) - file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n") + type = obj[2] + if (type == 'S'): + # for .S, .o depends on .s + file.write("%s: %s.s\n" % (obj[0], obj[3])) + file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n") + # and .s depends on .S + file.write("%s.s: %s\n" % (obj[3], source)) + # Note: next 2 lines are ONE output line! + file.write("\t$(CPP) $(CPPFLAGS) $< ") + file.write(">$@.new && mv $@.new $@\n") + else: + file.write("%s: %s\n" % (obj[0], source)) + file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n") #file.write("%s\n" % objrule[2]) for driverrule, driver in image.getdriverrules().items(): @@ -1501,34 +2166,40 @@ def writeimagemakefile(image): file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n") #file.write("%s\n" % objrule[2]) + file.write("\n# smmobjectrules:\n") + for irule, smm in image.getsmmobjectrules().items(): + source = topify(smm[1]) + type = smm[2] + if (type == 'S'): + # for .S, .o depends on .s + file.write("%s: %s.s\n" % (smm[0], smm[3])) + file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n") + # and .s depends on .S + file.write("%s.s: %s\n" % (smm[3], source)) + # Note: next 2 lines are ONE output line! + file.write("\t$(CPP) $(CPPFLAGS) $< ") + file.write(">$@.new && mv $@.new $@\n") + else: + file.write("%s: %s\n" % (smm[0], source)) + file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n") + + # special rule for chip_target.c + file.write("static.o: static.c\n") + file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n") + # Print out the rules that will make cause the files # generated by NLBConfig.py to be remade if any dependencies change. file.write("\n# Remember the automatically generated files\n") file.write("GENERATED:=\n") - for genfile in [ 'Makefile', + for genfile in ['Makefile', 'nsuperio.c', - 'chip.c', - 'LinuxBIOSDoc.config' ]: + 'static.c', + 'corebootDoc.config' ]: file.write("GENERATED += %s\n" % genfile) - file.write("GENERATED += %s\n" % image.getincludefilename()) - - #file.write("\n# Remake Makefile (and the other files generated by\n") - #file.write("# NLBConfig.py) if any config dependencies change.\n") + file.write("GENERATED += %s\n" % image.getincludefilename()) - #for cfile in image.config_file_list: - # file.write("$(GENERATED): %s\n" % topify(cfile)) - - #for depfile in [ '%s' % top_config_file, # This a duplicate, remove? - # '$(TOP)/util/config/NLBConfig.py', - # '$(TOP)/src/arch/$(ARCH)/config/make.base' ]: - # file.write("$(GENERATED): %s\n" % depfile) - - #file.write("$(GENERATED):\n") - #file.write("\tpython $(TOP)/util/config/NLBConfig.py %s $(TOP)\n" - # % top_config_file) - - keys = image.getroot().uses_options.keys() + keys = global_options_by_order keys.sort() file.write("\necho:\n") for key in keys: @@ -1541,113 +2212,279 @@ def writeimagemakefile(image): file.write("\n") for i in m.actions: file.write("\t%s\n" % i) + writemakefilefooter(file, makefilepath) file.close() # def writemakefile(path): + global rommapping + global bootblocksize makefilepath = os.path.join(path, "Makefile") print "Creating", makefilepath - file = open(makefilepath, 'w+') + file = safe_open(makefilepath, 'w+') writemakefileheader(file, makefilepath) + # Hack to get the necessary settings (CONFIG_CBFS): + file.write("include %s/Makefile.settings\n\n" % romimages.keys()[0]) + # main rule - file.write("all: ") - for i in romimages.keys(): - file.write("%s-rom " % i) - file.write("\n\n") + file.write("ifeq \"$(CONFIG_CBFS)\" \"1\"\n") + file.write("\nall: ") + for i in buildroms: + file.write(" %sfs" % i.name) + file.write("\n") + file.write("else") + file.write("\nall: ") + for i in buildroms: + file.write(" %s" % i.name) + file.write("\n") + file.write("endif\n\n") + + # cbfstool rules + file.write("\ncbfstool:\n\tmkdir -p tools/lzma\n\t$(MAKE) -C $(TOP)/util/cbfstool obj=$(shell pwd)\n\n") + + file.write("include Makefile.settings\n\n") for i, o in romimages.items(): - file.write("%s-rom:\n" % o.getname()) + file.write("%s/coreboot.rom:\n" % o.getname()) file.write("\tif (cd %s; \\\n" % o.getname()) - file.write("\t\tmake linuxbios.rom)\\\n"); + file.write("\t\t$(MAKE) coreboot.rom)\\\n") file.write("\tthen true; else exit 1; fi;\n\n") + file.write("clean: ") + for i in romimages.keys(): + file.write(" %s-clean" % i) + file.write(" base-clean") + file.write("\n\n") + for i, o in romimages.items(): + file.write("%s-clean:\n" % o.getname()) + file.write("\t(cd %s; $(MAKE) clean)\n\n" % o.getname()) + file.write("base-clean:\n") + file.write("\trm -f romcc*\n\n") + + for i in buildroms: + file.write("%s:" % i.name) + for j in i.roms: + file.write(" %s/coreboot.rom " % j) + file.write("\n") + file.write("\t cat ") + for j in i.roms: + file.write(" %s/coreboot.rom " % j) + file.write("> %s\n\n" %i.name) + # build the bootblock here as well. + file.write("\n") + file.write("\t cat ") + for j in i.roms: + file.write(" %s/coreboot.strip " % j) + file.write("> %s.bootblock\n\n" %i.name) + + romsize = getoption("ROM_SIZE", image) + # i.name? That can not be right, can it? + file.write("%sfs: %s cbfstool\n" %(i.name,i.name)); + file.write("\trm -f coreboot.cbfs\n"); + file.write("\t./cbfstool %sfs create %s %s %s.bootblock\n" % (i.name, romsize, bootblocksize, i.name)) + for i in buildroms: + for j in i.roms: + #failover is a hack that will go away soon. + if (j != "failover") and (rommapping[j] != "/dev/null"): + file.write("\tif [ -f %s/cbfs-support ]; then ./cbfstool %sfs add-payload %s %s/payload `cat %s/cbfs-support`; fi\n" % (j, i.name, rommapping[j], j, j)) + file.write("\t ./cbfstool %sfs print\n" % i.name) + + file.write(".PHONY: all clean cbfstool") + for i in romimages.keys(): + file.write(" %s-clean" % i) + for i, o in romimages.items(): + file.write(" %s/coreboot.rom" % o.getname()) + file.write("\n\n") + + writemakefilefooter(file, makefilepath) file.close() def writeinitincludes(image): global include_pattern filepath = os.path.join(image.gettargetdir(), image.getincludefilename()) print "Creating", filepath - outfile = open(filepath, 'w+') + outfile = safe_open(filepath, 'w+') if (image.newformat()): - infile = open(image.getinitfile(), 'r') + infile = safe_open(image.getinitfile(), 'r') line = infile.readline() while (line): p = include_pattern.match(line) if (p): - for i, inc in image.getinitincludes().items(): + for i in image.getinitincludes(): + inc = image.getinitinclude(i) if (inc.getstring() == p.group(1)): outfile.write("#include \"%s\"\n" % inc.getpath()) else: - outfile.write(line); + outfile.write(line) line = infile.readline() infile.close() else: - for i in image.getinitincludes().keys(): + for i in image.getinitincludes(): outfile.write("#include <%s>\n" % i) outfile.close() def writeldoptions(image): - # Write Makefile.settings to seperate the settings - # from the actual makefile creation - # In practice you need to rerun NLBConfig.py to change - # these but in theory you shouldn't need to. - + """Write ldoptions file.""" filename = os.path.join(image.gettargetdir(), "ldoptions") print "Creating", filename - file = open(filename, 'w+') - for i in global_options.keys(): - if (isexported(i) and IsInt(getoption(i, image))): - file.write("%s = %s;\n" % (i, getformated(i, image))) + file = safe_open(filename, 'w+') + for o in global_exported_options: + if (hasvalue(o.name, image) and IsInt(getoption(o.name, image))): + file.write("%s = %s;\n" % (o.name, getformated(o.name, image))) + for o in image.exported_options: + if (not o in global_exported_options and hasvalue(o.name, image) and IsInt(getoption(o.name, image))): + file.write("%s = %s;\n" % (o.name, getformated(o.name, image))) file.close() -# Add any run-time checks to verify that parsing the configuration -# was successful -def verifyparse(image): - if (image.newformat() and image.getinitfile() == ''): - fatal("An init file must be specified") - def dumptree(part, lvl): - debug_print(1, "DUMPTREE ME is") + debug.info(debug.dumptree, "DUMPTREE ME is") part.dumpme(lvl) # dump the siblings -- actually are there any? not sure # siblings are: - debug_print(1, "DUMPTREE SIBLINGS are") - kid = part.siblings + debug.info(debug.dumptree, "DUMPTREE SIBLINGS are") + kid = part.next_sibling while (kid): kid.dumpme(lvl) - kid = kid.siblings + kid = kid.next_sibling # dump the kids - debug_print(1, "DUMPTREE KIDS are") + debug.info(debug.dumptree, "DUMPTREE KIDS are") #for kid in part.children: if (part.children): dumptree(part.children, lvl+1) - debug_print(1, "DONE DUMPTREE") + kid = part.next_sibling + while (kid): + if (kid.children): + dumptree(kid.children, lvl + 1) + kid = kid.next_sibling + debug.info(debug.dumptree, "DONE DUMPTREE") -def gencode(part, file): - debug_print(1, "GENCODE ME is") - part.gencode(file) +def writecode(image): + filename = os.path.join(img_dir, "static.c") + print "Creating", filename + file = safe_open(filename, 'w+') + file.write("#include \n") + file.write("#include \n") + for path in image.getconfigincludes().values(): + file.write("#include \"%s\"\n" % path) + file.write("\n/* pass 0 */\n") + gencode(image.getroot(), file, 0) + file.write("\n/* pass 1 */\n") + gencode(image.getroot(), file, 1) + file.close() + +def gencode(part, file, pass_num): + debug.info(debug.gencode, "GENCODE ME is") + part.gencode(file, pass_num) # dump the siblings -- actually are there any? not sure - # dump the kids - debug_print(1, "GENCODE SIBLINGS are") - kid = part.siblings + debug.info(debug.gencode, "GENCODE SIBLINGS are") + kid = part.next_sibling while (kid): - kid.gencode(file) - kid = kid.siblings - debug_print(1, "GENCODE KIDS are") - #for kid in part.children: + kid.gencode(file, pass_num) + kid = kid.next_sibling + # now dump the children + debug.info(debug.gencode, "GENCODE KIDS are") if (part.children): - gencode(part.children, file) - debug_print(1, "DONE GENCODE") + gencode(part.children, file, pass_num) + kid = part.next_sibling + while (kid): + if (kid.children): + gencode(kid.children, file, pass_num) + kid = kid.next_sibling + debug.info(debug.gencode, "DONE GENCODE") + +def writegraph(image): + filename = os.path.join(img_dir, "static.dot") + print "Creating", filename + file = safe_open(filename, 'w+') + file.write("digraph devicetree {\n") + file.write(" rankdir=LR\n") + genranks(image.getroot(), file, 0) + gennodes(image.getroot(), file) + gengraph(image.getroot(), file) + file.write("}\n") + file.close() +def genranks(part, file, level): + #file.write(" # Level %d\n" % level ) + file.write(" { rank = same; \"dev_%s_%d\"" % (part.type_name,part.instance )) + sib = part.next_sibling + while (sib): + file.write("; \"dev_%s_%d\"" % (sib.type_name, sib.instance)) + sib = sib.next_sibling + file.write("}\n" ) + # now dump the children + if (part.children): + genranks(part.children, file, level + 1) + + kid = part.next_sibling + while (kid): + if (kid.children): + genranks(kid.children, file, level + 1) + kid = kid.next_sibling + + +def gennodes(part, file): + file.write(" dev_%s_%d[shape=record, label=\"%s\"];\n" % (part.type_name,part.instance,part.graph_name() )) + sib = part.next_sibling + while (sib): + file.write(" dev_%s_%d[shape=record, label=\"%s\"];\n" % (sib.type_name,sib.instance,sib.graph_name() )) + sib = sib.next_sibling + # now dump the children + if (part.children): + gennodes(part.children, file) + + kid = part.next_sibling + while (kid): + if (kid.children): + gennodes(kid.children, file) + kid = kid.next_sibling + + +def gengraph(part, file): + if (part.parent != part): + file.write(" dev_%s_%d -> dev_%s_%d;\n" % \ + (part.parent.type_name, part.parent.instance, \ + part.type_name, part.instance )) + sib = part.next_sibling + while (sib): + file.write(" dev_%s_%d -> dev_%s_%d;\n" % \ + (sib.parent.type_name, sib.parent.instance, \ + sib.type_name, sib.instance )) + sib = sib.next_sibling + + kid = part.next_sibling + while (kid): + if (kid.children): + gengraph(kid.children, file) + kid = kid.next_sibling + + if (part.children): + gengraph(part.children, file) + +def verifyparse(): + """Add any run-time checks to verify that parsing the configuration + was successful""" + + for image in romimages.values(): + print("Verifying ROMIMAGE %s" % image.name) + if (image.newformat() and image.getinitfile() == ''): + fatal("An init file must be specified") + for op in image.exported_options: + if (getoptionvalue(op.name, op, image) == 0 and getoptionvalue(op.name, op, 0) == 0): + warning("Exported option %s has no value (check Options.lb)" % op.name); + print("Verifing global options") + for op in global_exported_options: + if (getoptionvalue(op.name, op, 0) == 0): + notice("Exported option %s has no value (check Options.lb)" % op.name); + #============================================================================= # MAIN PROGRAM #============================================================================= if __name__=='__main__': from sys import argv if (len(argv) < 3): - print 'Args: ' - sys.exit(1) + fatal("Args: ") top_config_file = os.path.abspath(sys.argv[1]) @@ -1655,57 +2492,66 @@ if __name__=='__main__': # Now read in the customizing script... loc.push(argv[1]) - if (not parse('board', open(argv[1], 'r').read())): + fp = safe_open(argv[1], 'r') + if (not parse('board', fp.read())): fatal("Could not parse file") loc.pop() - for r in romimages.keys(): - verifyparse(getdict(romimages, r)) + verifyparse() # no longer need to check if an options has been used alloptions = 1 for image_name, image in romimages.items(): - if (debug): - debug_print(1, "DEVICE TREE:") + if (debug.level(debug.dumptree)): + debug.info(debug.dumptree, "DEVICE TREE:") dumptree(image.getroot(), 0) img_dir = image.gettargetdir() if not os.path.isdir(img_dir): print "Creating directory %s" % img_dir os.makedirs(img_dir) - filename = os.path.join(img_dir, "chips.c") - print "Creating", filename - file = open(filename, 'w+') - # gen all the forward references - - i = 0 - file.write("struct chip ") - while (i <= image.numparts()): - if (i): - file.write("cdev%d "% i) - else: - file.write("root ") - i = i + 1 - file.write(";\n") - gencode(image.getroot(), file) - file.close() - - # crt0 includes - if (debug): - for i in image.getinitincludes().keys(): - debug_print(1, "crt0include file %s" % i) + + for objrule, obj in image.getobjectrules().items(): + sub_dir = img_dir + '/' + os.path.dirname(obj[0]) + if not os.path.isdir(sub_dir): + print "Creating sub directory %s" % sub_dir + os.makedirs(sub_dir) + + for driverrule, driver in image.getdriverrules().items(): + sub_dir = img_dir + '/' + os.path.dirname(driver[0]) + if not os.path.isdir(sub_dir): + print "Creating sub directory %s" % sub_dir + os.makedirs(sub_dir) + + for srule, smm in image.getsmmobjectrules().items(): + sub_dir = img_dir + '/' + os.path.dirname(smm[0]) + if not os.path.isdir(sub_dir): + print "Creating sub directory %s" % sub_dir + os.makedirs(sub_dir) + + for irule, init in image.getinitobjectrules().items(): + sub_dir = img_dir + '/' + os.path.dirname(init[0]) + if not os.path.isdir(sub_dir): + print "Creating sub directory %s" % sub_dir + os.makedirs(sub_dir) + + if (debug.level(debug.dump)): + for i in image.getinitincludes(): + debug.info(debug.dump, "crt0include file %s" % i) for i in image.getdriverrules().keys(): - debug_print(1, "driver file %s" % i) + debug.info(debug.dump, "driver file %s" % i) for i in image.getldscripts(): - debug_print(1, "ldscript file %s" % i) + debug.info(debug.dump, "ldscript file %s" % i) for i, m in image.getmakerules().items(): - debug_print(1, " makerule %s dep %s act %s" % (i, m.dependency, m.actions)) + debug.info(debug.dump, " makerule %s dep %s act %s" % (i, m.dependency, m.actions)) + writecode(image) writeimagesettings(image) writeinitincludes(image) writeimagemakefile(image) writeldoptions(image) + writegraph(image) writemakefilesettings(target_dir) writemakefile(target_dir)