diff options
Diffstat (limited to 'util/sconfig/config.g')
-rw-r--r-- | util/sconfig/config.g | 1029 |
1 files changed, 1029 insertions, 0 deletions
diff --git a/util/sconfig/config.g b/util/sconfig/config.g new file mode 100644 index 0000000000..db3c516583 --- /dev/null +++ b/util/sconfig/config.g @@ -0,0 +1,1029 @@ +# -*- python -*- +import sys +import os +import re +import string +import types + +import traceback + +warnings = 0 +errors = 0 + +treetop = '' +full_mainboard_path = '' +mainboard_path = '' +romimages = {} +curimage = 0 + +# ----------------------------------------------------------------------------- +# Utility Classes +# ----------------------------------------------------------------------------- + +class stack: + """Used to keep track of the current part or dir""" + class __stack_iter: + def __init__ (self, stack): + self.index = 0 + self.len = len(stack) + self.stack = stack + + def __iter__ (self): + return self + + def next (self): + if (self.index < self.len): + s = self.stack[self.index] + self.index = self.index + 1 + return s + raise StopIteration + + def __init__ (self): + self.stack = [] + + def __len__ (self): + return len(self.stack) + + def __getitem__ (self, i): + return self.stack[i] + + def __iter__ (self): + return self.__stack_iter(self.stack) + + def push(self, part): + self.stack.append(part) + + def pop(self): + try: + return self.stack.pop() + except IndexError: + return 0 + + def tos(self): + try: + return self.stack[-1] + except IndexError: + return 0 + + def empty(self): + return (len(self.stack) == 0) +partstack = 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.none) +#debug = debug_info(debug_info.dumptree) +#debug = debug_info(debug_info.object) +#debug = debug_info(debug_info.gencode) + +# ----------------------------------------------------------------------------- +# Error Handling +# ----------------------------------------------------------------------------- + +def error(string): + """Print error message""" + global errors, loc + errors = errors + 1 + print "===> ERROR: %s" % string + +def fatal(string): + """Print error message and exit""" + error(string) + exitiferrors() + +def warning(string): + """Print warning message""" + global warnings, loc + warnings = warnings + 1 + print "===> WARNING: %s" % string + +def exitiferrors(): + """Exit parser if an error has been encountered""" + if (errors != 0): + sys.exit(1) + +def safe_open(file, mode): + try: + return open(file, mode) + except IOError: + fatal("Could not open file \"%s\"" % file) + +# ----------------------------------------------------------------------------- +# Main classes +# ----------------------------------------------------------------------------- + +class romimage: + """A rom image is the ultimate goal of coreboot""" + def __init__ (self, name): + # name of this rom image + self.name = name + + # instance counter for parts + self.partinstance = 0 + + # chip config files included by the 'config' directive + self.configincludes = {} + + # root of part tree + self.root = 0 + + # Last device built + self.last_device = 0 + + def getname(self): + return self.name + + 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_includes.h" + + def newformat(self): + return self.useinitincludes + + def numparts(self): + return self.partinstance + + def newpartinstance(self): + i = self.partinstance + self.partinstance = self.partinstance + 1 + return i + + def setroot(self, part): + self.root = part + + def getroot(self): + return self.root + +class partobj: + """A configuration part""" + def __init__ (self, image, dir, parent, part, type_name, instance_name, chip_or_device): + if (parent): + debug.info(debug.object, "partobj dir %s parent %s part %s" \ + % (dir, parent.instance_name, part)) + else: + debug.info(debug.object, "partobj dir %s part %s" \ + % (dir, 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 + + # initializers for static device tree + self.registercode = {} + + # part name + self.part = part + + # type name of this part + self.type_name = type_name + + # directory containing part files + self.dir = dir + + # instance number, used to distinguish anonymous + # instances of this part + self.instance = image.newpartinstance() + debug.info(debug.object, "INSTANCE %d" % self.instance) + + # 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 duplicate device + self.dup = 0 + + # If there is a chip.h file, we will create an + # include for it. + if (dir): + chiph = os.path.join(dir, "chip.h") + if (os.path.exists(chiph)): + debug.info(debug.object, "%s has chip at %s" % (self, dir)) + self.addconfig(chiph) + + # 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.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.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): + """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: 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.readable_name()) + if (self.next_sibling): + print "%d: siblings %s" % (lvl, self.next_sibling.readable_name()) + print "%d: registercode " % lvl + for f, v in self.registercode.items(): + print "\t%s = %s" % (f, v) + print "%d: chipconfig %s" % (lvl, self.chipconfig) + print "\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: + 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") + return + + 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)) + + +# ----------------------------------------------------------------------------- +# statements +# ----------------------------------------------------------------------------- + +def getdict(dict, name): + if name not in dict.keys(): + debug.info(debug.dict, "Undefined: %s" % name) + return 0 + v = dict.get(name, 0) + debug.info(debug.dict, "getdict %s returning %s" % (name, v)) + return v + +def setdict(dict, 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 + + +def addconfig(path): + global partstack + curpart = partstack.tos() + curpart.addconfig(path) + +def addregister(field, value): + global partstack + curpart = partstack.tos() + curpart.addregister(field, value) + +def devicepart(type): + global curimage, 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. + +def part(type, path, file, name): + global curimage, partstack + partdir = os.path.join(type, path) + srcdir = os.path.join(treetop, 'src') + fulldir = os.path.join(srcdir, partdir) + type_name = flatten_name(partdir) + #print "PART(%s, %s, %s, %s)\n" % (type, path, file, name) + newpart = partobj(curimage, fulldir, partstack.tos(), type, \ + type_name, name, 'chip') + #print "Configuring PART %s, path %s" % (type, path) + partstack.push(newpart) + +def partpop(): + global partstack + curpart = partstack.tos() + if (curpart == 0): + fatal("Trying to pop non-existent part") + #print "End PART %s" % curpart.part + oldpart = partstack.pop() + #print "partstack.pop, TOS is now %s\n" % oldpart.info() + +#============================================================================= +# MISC FUNCTIONS +#============================================================================= +def dequote(str): + a = re.sub("^\"", "", str) + a = re.sub("\"$", "", a) + # highly un-intuitive, need four \! + a = re.sub("\\\\\"", "\"", a) + return a + +def flatten_name(str): + a = re.sub("[/-]", "_", str) + return a +%% +parser Config: + ignore: r'\s+' + ignore: "#.*?\r?\n" + + # less general tokens should come first, otherwise they get matched + # by the re's + token COMMENT: 'comment' + token CPU: 'cpu' + token CPU_BUS: 'cpu_bus' + token CHIP: 'chip' + token DEVICE: 'device' + token DEVICE_ID: 'device_id' + token DRQ: 'drq' + token END: 'end' + token EOF: '$' + token EQ: '=' + token FORMAT: 'format' + token IO: 'io' + token IRQ: 'irq' + token MEM: 'mem' + token NEVER: 'never' + token NONE: 'none' + token PMC: 'pmc' + token PRINT: 'print' + token REGISTER: 'register' + token VENDOR_ID: 'vendor_id' + 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_.]+' + # 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 ID: r'[a-zA-Z_.]+[a-zA-Z0-9_.]*' + 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 }} + | "[|][|]" logical {{ l = l or logical }} + )* {{ return l }} + + rule logical: factor {{ n = factor }} + ( "[+]" factor {{ n = n+factor }} + | "-" factor {{ n = n-factor }} + )* {{ return n }} + + rule factor: term {{ v = term }} + ( "[*]" term {{ v = v*term }} + | "/" term {{ v = v/term }} + | "<<" term {{ v = v << term }} + | ">=" term {{ v = (v < term)}} + )* {{ return v }} + + # A term is a number, variable, or an expression surrounded by parentheses + 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 }} + + rule unop: "!" expr {{ return not(expr) }} + + rule partend<<C>>: (stmt<<C>>)* END {{ if (C): partpop()}} + + # 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: CHIP {{ return '' }} + + rule partdef<<C>>: {{ name = 0 }} + parttype partid + [ STR {{ name = dequote(STR) }} + ] {{ if (C): part(parttype, partid, 'Config.lb', name) }} + partend<<C>> + + rule field: STR {{ return STR }} + + rule register<<C>>: REGISTER field '=' STR {{ if (C): addregister(field, STR) }} + + rule enable<<C>>: {{ val = 1 }} + ( ON {{ val = 1 }} + | OFF {{ val = 0 }} + ) {{ if(C): partstack.tos().set_enabled(val) }} + + rule resource<<C>>: {{ 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<<C>>: {{ if (C): partstack.tos().start_resources() }} + ( resource<<C>> )* + {{ if (C): partstack.tos().end_resources() }} + + + rule pci<<C>>: 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<<C>>: + 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<<C>>: 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<<C>>: I2C {{ if (C): devicepart('i2c') }} + HEX_NUM {{ device = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addi2cpath(device) }} + + rule apic<<C>>: APIC {{ if (C): devicepart('apic') }} + HEX_NUM {{ apic_id = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addapicpath(apic_id) }} + + rule apic_cluster<<C>>: APIC_CLUSTER {{ if (C): devicepart('apic_cluster') }} + HEX_NUM {{ cluster = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addapic_clusterpath(cluster) }} + + rule cpu<<C>>: CPU {{ if (C): devicepart('cpu') }} + HEX_NUM {{ id = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addcpupath(id) }} + + rule cpu_bus<<C>>: CPU_BUS {{ if (C): devicepart('cpu_bus') }} + HEX_NUM {{ id = int(HEX_NUM, 16) }} + {{ if (C): partstack.tos().addcpu_buspath(id) }} + + rule dev_path<<C>>: + pci<<C>> {{ return pci }} + | pci_domain<<C>> {{ return pci_domain }} + | pnp<<C>> {{ return pnp }} + | i2c<<C>> {{ return i2c }} + | apic<<C>> {{ return apic }} + | apic_cluster<<C>> {{ return apic_cluster }} + | cpu<<C>> {{ return cpu }} + | cpu_bus<<C>> {{ return cpu_bus }} + + rule prtval: expr {{ return str(expr) }} + | STR {{ return STR }} + + rule prtlist: prtval {{ el = "%(" + prtval }} + ( "," prtval {{ el = el + "," + prtval }} + )* {{ return el + ")" }} + + rule prtstmt<<C>>: PRINT STR {{ val = STR }} + [ "," prtlist {{ val = val + prtlist }} + ] {{ if (C): print eval(val) }} + + rule device<<C>>: DEVICE dev_path<<C>> + enable<<C>> + resources<<C>> + partend<<C>> + + rule stmt<<C>>: + partdef<<C>> {{ return partdef }} + | prtstmt<<C>> {{ return prtstmt }} + | register<<C>> {{ return register }} + | device<<C>> {{ return device }} + + rule value: STR {{ return dequote(STR) }} + | expr {{ return expr }} + + rule devicetree: partdef<<1>> + EOF {{ return 1 }} + + rule wrstr<<ID>>: STR {{ setwrite(ID, dequote(STR)) }} + +%% + +#============================================================================= +# FILE OUTPUT +#============================================================================= + +def dumptree(part, lvl): + debug.info(debug.dumptree, "DUMPTREE ME is") + print "%s " % part + part.dumpme(lvl) + # dump the siblings -- actually are there any? not sure + # siblings are: + debug.info(debug.dumptree, "DUMPTREE SIBLINGS are") + kid = part.next_sibling + while (kid): + kid.dumpme(lvl) + kid = kid.next_sibling + # dump the kids + debug.info(debug.dumptree, "DUMPTREE KIDS are") + #for kid in part.children: + if (part.children): + dumptree(part.children, lvl+1) + 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 writecode(image): + filename = os.path.join(img_dir, "static.c") + print "Creating", filename + file = safe_open(filename, 'w+') + file.write("#include <device/device.h>\n") + file.write("#include <device/pci.h>\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 + debug.info(debug.gencode, "GENCODE SIBLINGS are") + kid = part.next_sibling + while (kid): + 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, 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) + +#============================================================================= +# MAIN PROGRAM +#============================================================================= +if __name__=='__main__': + from sys import argv + if (len(argv) < 4): + fatal("Args: <file> <path to coreboot> <output-dir>") + + file = "devicetree.cb" + partdir = os.path.join("mainboard", sys.argv[1]) + treetop = argv[2] + srcdir = os.path.join(treetop, 'src') + fulldir = os.path.join(srcdir, partdir) + type_name = flatten_name(partdir) + config_file = os.path.join(fulldir, file) + + curimage = romimage("new") + image = curimage + + newpart = partobj(curimage, fulldir, partstack.tos(), 'mainboard', \ + 'mainboard', 0, 'chip') + #print "Configuring PART %s, path %s" % (type, path) + image.setroot(newpart); + partstack.push(newpart) + + fp = safe_open(config_file, 'r') + if (not parse('devicetree', fp.read())): + fatal("Could not parse file") + print "PARSED THE TREE" + partstack.pop() + + img_dir = argv[3] + + #debug.info(debug.dumptree, "DEVICE TREE:") + #dumptree(curimage.getroot(), 0) + + writecode(image) + writegraph(image) + + sys.exit(0) |