summaryrefslogtreecommitdiff
path: root/util/sconfig/config.g
diff options
context:
space:
mode:
Diffstat (limited to 'util/sconfig/config.g')
-rw-r--r--util/sconfig/config.g1029
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)