Improve coreboot build output and eliminate some warnings:
[coreboot.git] / util / sconfig / config.g
1 # -*- python -*-
2 import sys
3 import os
4 import re
5 import string
6 import types
7
8 import traceback
9
10 warnings = 0
11 errors = 0
12
13 treetop = ''
14 full_mainboard_path = ''
15 mainboard_path = ''
16 romimages = {}
17 curimage = 0
18
19 # -----------------------------------------------------------------------------
20 #                    Utility Classes
21 # -----------------------------------------------------------------------------
22
23 class stack:
24         """Used to keep track of the current part or dir"""
25         class __stack_iter:
26                 def __init__ (self, stack):
27                         self.index = 0
28                         self.len = len(stack)
29                         self.stack = stack
30
31                 def __iter__ (self):
32                         return self
33
34                 def next (self):
35                         if (self.index < self.len):
36                                 s = self.stack[self.index]
37                                 self.index = self.index + 1
38                                 return s
39                         raise StopIteration
40
41         def __init__ (self):
42                 self.stack = []
43
44         def __len__ (self):
45                 return len(self.stack)
46
47         def __getitem__ (self, i):
48                 return self.stack[i]
49
50         def __iter__ (self):
51                 return self.__stack_iter(self.stack)
52
53         def push(self, part):
54                 self.stack.append(part)
55
56         def pop(self):
57                 try:
58                         return self.stack.pop()
59                 except IndexError:
60                         return 0
61
62         def tos(self):
63                 try:
64                         return self.stack[-1]
65                 except IndexError:
66                         return 0
67
68         def empty(self):
69                 return (len(self.stack) == 0)
70 partstack = stack()
71
72 class debug_info:
73         none = 0
74         gencode = 1
75         dumptree = 2
76         object = 3
77         dict = 4
78         statement = 5
79         dump = 6
80         gengraph = 7
81
82         def __init__(self, *level):
83                 self.__level = level
84
85         def setdebug(self, *level):
86                 self.__level = level
87
88         def level(self, level):
89                 return level in self.__level
90
91         def info(self, level, str):
92                 if level in self.__level:
93                         print str
94
95 global debug
96 debug = debug_info(debug_info.none)
97 #debug = debug_info(debug_info.dumptree)
98 #debug = debug_info(debug_info.object)
99 #debug = debug_info(debug_info.gencode)
100
101 # -----------------------------------------------------------------------------
102 #                    Error Handling
103 # -----------------------------------------------------------------------------
104
105 def error(string):      
106         """Print error message"""
107         global errors, loc
108         errors = errors + 1
109         print "===> ERROR: %s" % string
110
111 def fatal(string):      
112         """Print error message and exit"""
113         error(string)
114         exitiferrors()
115
116 def warning(string):
117         """Print warning message"""
118         global warnings, loc
119         warnings = warnings + 1
120         print "===> WARNING: %s" % string
121
122 def exitiferrors():
123         """Exit parser if an error has been encountered"""
124         if (errors != 0):
125                 sys.exit(1)
126
127 def safe_open(file, mode):
128         try:
129                 return open(file, mode)
130         except IOError:
131                 fatal("Could not open file \"%s\"" % file)
132
133 # -----------------------------------------------------------------------------
134 #                    Main classes
135 # -----------------------------------------------------------------------------
136
137 class romimage:
138         """A rom image is the ultimate goal of coreboot"""
139         def __init__ (self, name):
140                 # name of this rom image
141                 self.name = name
142
143                 # instance counter for parts
144                 self.partinstance = 0
145
146                 # chip config files included by the 'config' directive
147                 self.configincludes = {}
148
149                 # root of part tree
150                 self.root = 0
151
152                 # Last device built
153                 self.last_device = 0
154
155         def getname(self):
156                 return self.name
157
158         def addconfiginclude(self, part, path):
159                 setdict(self.configincludes, part, path)
160
161         def getconfigincludes(self):
162                 return self.configincludes
163
164         def getincludefilename(self):
165                 if (self.useinitincludes):
166                         return "crt0.S"
167                 else:
168                         return "crt0_includes.h"
169         
170         def newformat(self):
171                 return self.useinitincludes
172
173         def numparts(self):
174                 return self.partinstance
175
176         def newpartinstance(self):
177                 i = self.partinstance
178                 self.partinstance = self.partinstance + 1
179                 return i
180
181         def setroot(self, part):
182                 self.root = part
183
184         def getroot(self):
185                 return self.root
186
187 class partobj:
188         """A configuration part"""
189         def __init__ (self, image, dir, parent, part, type_name, instance_name, chip_or_device):
190                 if (parent):
191                         debug.info(debug.object, "partobj dir %s parent %s part %s" \
192                                 % (dir, parent.instance_name, part))
193                 else:
194                         debug.info(debug.object, "partobj dir %s part %s" \
195                                 % (dir, part))
196
197                 # romimage that is configuring this part
198                 self.image = image
199
200                 # links for static device tree
201                 self.children = 0
202                 self.prev_sibling = 0
203                 self.next_sibling = 0
204                 self.prev_device = 0
205                 self.next_device = 0
206                 self.chip_or_device = chip_or_device
207
208                 # initializers for static device tree
209                 self.registercode = {}
210
211                 # part name
212                 self.part = part
213
214                 # type name of this part
215                 self.type_name = type_name
216
217                 # directory containing part files
218                 self.dir = dir
219
220                 # instance number, used to distinguish anonymous
221                 # instances of this part
222                 self.instance = image.newpartinstance()
223                 debug.info(debug.object, "INSTANCE %d" % self.instance)
224
225                 # Name of chip config file (0 if not needed)
226                 self.chipconfig = 0
227
228                 # Flag to indicate that we have generated type
229                 # definitions for this part (only want to do it once)
230                 self.done_types = 0
231
232                 # Path to the device
233                 self.path = ""
234
235                 # Resources of the device
236                 self.resoruce = ""
237                 self.resources = 0
238
239                 # Enabled state of the device
240                 self.enabled = 1
241
242                 # Flag if I am a duplicate device
243                 self.dup = 0
244
245                 # If there is a chip.h file, we will create an 
246                 # include for it. 
247                 if (dir):
248                         chiph = os.path.join(dir, "chip.h")
249                         if (os.path.exists(chiph)):
250                                 debug.info(debug.object,  "%s has chip at %s" % (self, dir))
251                                 self.addconfig(chiph)
252
253                 # If no instance name is supplied then generate
254                 # a unique name
255                 if (instance_name == 0):
256                         self.instance_name = self.type_name + \
257                                         "_dev%d" % self.instance
258                         self.chipinfo_name = "%s_info_%d" \
259                                         % (self.type_name, self.instance)
260                 else:
261                         self.instance_name = instance_name
262                         self.chipinfo_name = "%s_info_%d" % (self.instance_name, self.instance)
263
264                 # Link this part into the device list
265                 if (self.chip_or_device == 'device'):
266                         if (image.last_device):
267                                 image.last_device.next_device = self
268                         self.prev_device = image.last_device
269                         image.last_device = self
270
271                 # Link this part into the tree
272                 if (parent and (part != 'arch')):
273                         debug.info(debug.gencode, "add to parent")
274                         self.parent   = parent
275                         # add current child as my sibling, 
276                         # me as the child.
277                         if (parent.children):
278                                 debug.info(debug.gencode, "add %s (%d) as sibling" % (parent.children.dir, parent.children.instance))
279                                 youngest = parent.children
280                                 while(youngest.next_sibling):
281                                         youngest = youngest.next_sibling
282                                 youngest.next_sibling = self
283                                 self.prev_sibling = youngest
284                         else:
285                                 parent.children = self
286                 else:
287                         self.parent = self
288
289         def info(self):
290                 return "%s: %s" % (self.part, self.type)
291         def type(self):
292                 return self.chip_or_device
293
294         def readable_name(self):
295                 name = ""
296                 name = "%s_%d" % (self.type_name, self.instance)
297                 if (self.chip_or_device == 'chip'):
298                         name = "%s %s %s" % (name, self.part, self.dir)
299                 else:
300                         name = "%s %s" % (name, self.path)
301                 return name
302
303         def graph_name(self):
304                 name = "{ {_dev%d|" % self.instance
305                 if (self.part):
306                         name = "%s%s" % (name, self.part)
307                 else:
308                         name = "%s%s" % (name, self.chip_or_device)
309                 if (self.type_name):
310                         name = "%s}|%s}" % (name, self.type_name)
311                 else:
312                         name = "%s}|%s}" % (name, self.parent.type_name)
313                 return name
314                         
315         def dumpme(self, lvl):
316                 """Dump information about this part for debugging"""
317                 print "%d: %s" % (lvl, self.readable_name())
318                 print "%d: part %s" % (lvl, self.part)
319                 print "%d: instance %d" % (lvl, self.instance)
320                 print "%d: chip_or_device %s"  %  (lvl, self.chip_or_device)
321                 print "%d: dir %s" % (lvl,self.dir)
322                 print "%d: type_name %s" % (lvl,self.type_name)
323                 print "%d: parent: %s" % (lvl, self.parent.readable_name())
324                 if (self.children):
325                         print "%d: child %s" % (lvl, self.children.readable_name())
326                 if (self.next_sibling):
327                         print "%d: siblings %s" % (lvl, self.next_sibling.readable_name())
328                 print "%d: registercode " % lvl
329                 for f, v in self.registercode.items():
330                         print "\t%s = %s" % (f, v)
331                 print "%d: chipconfig %s" % (lvl, self.chipconfig)
332                 print "\n"
333
334         def firstchilddevice(self):
335                 """Find the first device in the children link."""
336                 kid = self.children
337                 while (kid):
338                         if (kid.chip_or_device == 'device'):
339                                 return kid
340                         else:
341                                 kid = kid.children
342                 return 0
343
344         def firstparentdevice(self):
345                 """Find the first device in the parent link."""
346                 parent = self.parent
347                 while (parent and (parent.parent != parent) and (parent.chip_or_device != 'device')):
348                         parent = parent.parent
349                 if ((parent.parent != parent) and (parent.chip_or_device != 'device')):
350                         parent = 0
351                 while(parent and (parent.dup == 1)):
352                         parent = parent.prev_sibling
353                 if (not parent):
354                         fatal("Device %s has no device parent; this is a config file error" % self.readable_name())
355                 return parent
356
357         def firstparentdevicelink(self):
358                 """Find the first device in the parent link and record which link it is."""
359                 link = 0
360                 parent = self.parent
361                 while (parent and (parent.parent != parent) and (parent.chip_or_device != 'device')):
362                         parent = parent.parent
363                 if ((parent.parent != parent) and (parent.chip_or_device != 'device')):
364                         parent = 0
365                 while(parent and (parent.dup == 1)):
366                         parent = parent.prev_sibling
367                         link = link + 1
368                 if (not parent):
369                         fatal("Device %s has no device parent; this is a config file error" % self.readable_name())
370                 return link
371
372
373         def firstparentchip(self):
374                 """Find the first chip in the parent link."""
375                 parent = self.parent
376                 while (parent):
377                         if ((parent.parent == parent) or (parent.chip_or_device == 'chip')):
378                                 return parent
379                         else:
380                                 parent = parent.parent
381                 fatal("Device %s has no chip parent; this is a config file error" % self.readable_name())
382
383         def firstsiblingdevice(self):
384                 """Find the first device in the sibling link."""
385                 sibling = self.next_sibling
386                 while(sibling and (sibling.path == self.path)):
387                         sibling = sibling.next_sibling
388                 if ((not sibling) and (self.parent.chip_or_device == 'chip')):
389                         sibling = self.parent.next_sibling
390                 while(sibling):
391                         if (sibling.chip_or_device == 'device'):
392                                 return sibling
393                         else:
394                                 sibling = sibling.children
395                 return 0
396
397         def gencode(self, file, pass_num):
398                 """Generate static initalizer code for this part. Two passes
399                 are used - the first generates type information, and the second
400                 generates instance information"""
401                 if (pass_num == 0):
402                         if (self.chip_or_device == 'chip'):
403                                 return;
404                         else:
405                                 if (self.instance):
406                                         file.write("struct device %s;\n" \
407                                                 % self.instance_name)
408                                 else:
409                                         file.write("struct device dev_root;\n")
410                         return
411                 # This is pass the second, which is pass number 1
412                 # this is really just a case statement ...
413
414                 if (self.chip_or_device == 'chip'):
415                         if (self.chipconfig):
416                                 debug.info(debug.gencode, "gencode: chipconfig(%d)" % \
417                                         self.instance)
418                                 file.write("struct %s_config %s" % (self.type_name ,\
419                                         self.chipinfo_name))
420                                 if (self.registercode):
421                                         file.write("\t= {\n")
422                                         for f, v in self.registercode.items():
423                                                 file.write( "\t.%s = %s,\n" % (f, v))
424                                         file.write("};\n")
425                                 else:
426                                         file.write(";")
427                                 file.write("\n")
428
429                         if (self.instance == 0):
430                                 self.instance_name = "dev_root"
431                                 file.write("struct device **last_dev_p = &%s.next;\n" % (self.image.last_device.instance_name))
432                                 file.write("struct device dev_root = {\n")
433                                 file.write("\t.ops = &default_dev_ops_root,\n")
434                                 file.write("\t.bus = &dev_root.link[0],\n")
435                                 file.write("\t.path = { .type = DEVICE_PATH_ROOT },\n")
436                                 file.write("\t.enabled = 1,\n\t.links = 1,\n")
437                                 file.write("\t.on_mainboard = 1,\n")
438                                 file.write("\t.link = {\n\t\t[0] = {\n")
439                                 file.write("\t\t\t.dev=&dev_root,\n\t\t\t.link = 0,\n")
440                                 file.write("\t\t\t.children = &%s,\n" % self.firstchilddevice().instance_name)
441                                 file.write("\t\t},\n")
442                                 file.write("\t},\n")
443                                 if (self.chipconfig):
444                                         file.write("\t.chip_ops = &%s_ops,\n" % self.type_name)
445                                         file.write("\t.chip_info = &%s_info_%s,\n" % (self.type_name, self.instance))
446                                 file.write("\t.next = &%s,\n" % self.firstchilddevice().instance_name)
447                                 file.write("};\n")
448                         return
449
450                 # Don't print duplicate devices, just print their children
451                 if (self.dup):
452                         return
453
454                 file.write("struct device %s = {\n" % self.instance_name)
455                 file.write("\t.ops = 0,\n")
456                 file.write("\t.bus = &%s.link[%d],\n" % \
457                         (self.firstparentdevice().instance_name, \
458                         self.firstparentdevicelink()))
459                 file.write("\t.path = {%s},\n" % self.path)
460                 file.write("\t.enabled = %d,\n" % self.enabled)
461                 file.write("\t.on_mainboard = 1,\n")
462                 if (self.resources):
463                         file.write("\t.resources = %d,\n" % self.resources)
464                         file.write("\t.resource = {%s\n\t },\n" % self.resource)
465                 file.write("\t.link = {\n");    
466                 links = 0
467                 bus = self
468                 while(bus and (bus.path == self.path)):
469                         child = bus.firstchilddevice()
470                         if (child or (bus != self) or (bus.next_sibling and (bus.next_sibling.path == self.path))):
471                                 file.write("\t\t[%d] = {\n" % links)
472                                 file.write("\t\t\t.link = %d,\n" % links)
473                                 file.write("\t\t\t.dev = &%s,\n" % self.instance_name)
474                                 if (child):
475                                         file.write("\t\t\t.children = &%s,\n" %child.instance_name)
476                                 file.write("\t\t},\n")
477                                 links = links + 1
478                         if (1): 
479                                 bus = bus.next_sibling
480                         else:
481                                 bus = 0
482                 file.write("\t},\n")
483                 file.write("\t.links = %d,\n" % (links))
484                 sibling = self.firstsiblingdevice(); 
485                 if (sibling):
486                         file.write("\t.sibling = &%s,\n" % sibling.instance_name)
487                 chip = self.firstparentchip()
488                 if (chip and chip.chipconfig):
489                         file.write("\t.chip_ops = &%s_ops,\n" % chip.type_name)
490                         file.write("\t.chip_info = &%s_info_%s,\n" % (chip.type_name, chip.instance))
491                 if (self.next_device):  
492                         file.write("\t.next=&%s\n" % self.next_device.instance_name)
493                 file.write("};\n")
494                 return
495                 
496         def addconfig(self, path):
497                         """Add chip config file to this part"""
498                         self.chipconfig = os.path.join(self.dir, path)
499                         self.image.addconfiginclude(self.type_name, self.chipconfig)
500
501         def addregister(self, field, value):
502                         """Register static initialization information"""
503                         if (self.chip_or_device != 'chip'):
504                                 fatal("Only chips can have register values")
505                         field = dequote(field)
506                         value = dequote(value)
507                         setdict(self.registercode, field, value)
508
509         def set_enabled(self, enabled):
510                 self.enabled = enabled
511
512         def start_resources(self):
513                 self.resource = ""
514                 self.resources = 0
515
516         def end_resources(self):
517                 self.resource = "%s" % (self.resource)
518
519         def add_resource(self, type, index, value):
520                 """ Add a resource to a device """
521                 self.resource = "%s\n\t\t{ .flags=%s, .index=0x%x, .base=0x%x}," % (self.resource, type, index, value)
522                 self.resources = self.resources + 1
523
524         def set_path(self, path):
525                 self.path = path
526                 if (self.prev_sibling and (self.prev_sibling.path == self.path)):
527                         self.dup = 1
528                         if (self.prev_device):
529                                 self.prev_device.next_device = self.next_device
530                         if (self.next_device):  
531                                 self.next_device.prev_device = self.prev_device
532                         if (self.image.last_device == self):
533                                 self.image.last_device = self.prev_device
534                         self.prev_device = 0
535                         self.next_device = 0
536                 
537         def addpcipath(self, slot, function):
538                 """ Add a relative pci style path from our parent to this device """
539                 if ((slot < 0) or (slot > 0x1f)):
540                         fatal("Invalid device id")
541                 if ((function < 0) or (function > 7)):
542                         fatal("Invalid pci function %s" % function )
543                 self.set_path(".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}" % (slot, function))
544
545         def addpnppath(self, port, device):
546                 """ Add a relative path to a pnp device hanging off our parent """
547                 if ((port < 0) or (port > 65536)):
548                         fatal("Invalid port")
549                 if ((device < 0) or (device > 0xffff)):
550                         fatal("Invalid device")
551                 self.set_path(".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}" % (port, device))
552                 
553         def addi2cpath(self, device):
554                 """ Add a relative path to a i2c device hanging off our parent """
555                 if ((device < 0) or (device > 0x7f)):
556                         fatal("Invalid device")
557                 self.set_path(".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}" % (device))
558
559         def addapicpath(self, apic_id):
560                 """ Add a relative path to a cpu device hanging off our parent """
561                 if ((apic_id < 0) or (apic_id > 255)):
562                         fatal("Invalid device")
563                 self.set_path(".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}" % (apic_id))
564     
565         def addpci_domainpath(self, pci_domain):
566                 """ Add a pci_domain number to a chip """
567                 if ((pci_domain < 0) or (pci_domain > 0xffff)):
568                         fatal("Invalid pci_domain: 0x%x is out of the range 0 to 0xffff" % pci_domain)
569                 self.set_path(".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}" % (pci_domain))
570     
571         def addapic_clusterpath(self, cluster):
572                 """ Add an apic cluster to a chip """
573                 if ((cluster < 0) or (cluster > 15)):
574                         fatal("Invalid apic cluster: %d is out of the range 0 to ff" % cluster)
575                 self.set_path(".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}" % (cluster))
576     
577         def addcpupath(self, cpu_id):
578                 """ Add a relative path to a cpu device hanging off our parent """
579                 if ((cpu_id < 0) or (cpu_id > 255)):
580                         fatal("Invalid device")
581                 self.set_path(".type=DEVICE_PATH_CPU,{.cpu={ .id = 0x%x }}" % (cpu_id))
582     
583
584         def addcpu_buspath(self, id):
585                 """ Add a cpu_bus to a chip """
586                 if ((id < 0) or (id > 255)):
587                         fatal("Invalid device")
588                 self.set_path(".type=DEVICE_PATH_CPU_BUS,{.cpu_bus={ .id = 0x%x }}" % (id))
589     
590
591 # -----------------------------------------------------------------------------
592 #                    statements 
593 # -----------------------------------------------------------------------------
594
595 def getdict(dict, name):
596         if name not in dict.keys(): 
597                 debug.info(debug.dict, "Undefined: %s" % name)
598                 return 0
599         v = dict.get(name, 0)
600         debug.info(debug.dict, "getdict %s returning %s" % (name, v))
601         return v
602
603 def setdict(dict, name, value):
604         debug.info(debug.dict, "setdict sets %s to %s" % (name, value))
605         if name in dict.keys():
606                 print "Duplicate in dict: %s" % name
607         dict[name] = value
608
609
610 def addconfig(path):
611         global partstack
612         curpart = partstack.tos()
613         curpart.addconfig(path)
614
615 def addregister(field, value):
616         global partstack
617         curpart = partstack.tos()
618         curpart.addregister(field, value)
619
620 def devicepart(type):
621         global curimage, partstack
622         newpart = partobj(curimage, 0, partstack.tos(), type, \
623                         '', 0, 'device')
624         #print "Configuring PART %s" % (type)
625         partstack.push(newpart)
626         #print "  new PART tos is now %s\n" %partstack.tos().info()
627         # just push TOS, so that we can pop later. 
628         
629 def part(type, path, file, name):
630         global curimage, partstack
631         partdir = os.path.join(type, path)
632         srcdir = os.path.join(treetop, 'src')
633         fulldir = os.path.join(srcdir, partdir)
634         type_name = flatten_name(partdir)
635         #print "PART(%s, %s, %s, %s)\n" % (type, path, file, name)
636         newpart = partobj(curimage, fulldir, partstack.tos(), type, \
637                         type_name, name, 'chip')
638         #print "Configuring PART %s, path %s" % (type, path)
639         partstack.push(newpart)
640
641 def partpop():
642         global partstack
643         curpart = partstack.tos()
644         if (curpart == 0):
645                 fatal("Trying to pop non-existent part")
646         #print "End PART %s" % curpart.part
647         oldpart = partstack.pop()
648         #print "partstack.pop, TOS is now %s\n" % oldpart.info()
649
650 #=============================================================================
651 #               MISC FUNCTIONS
652 #=============================================================================
653 def dequote(str):
654         a = re.sub("^\"", "", str)
655         a = re.sub("\"$", "", a)
656         # highly un-intuitive, need four \!
657         a = re.sub("\\\\\"", "\"", a)
658         return a
659
660 def flatten_name(str):
661         a = re.sub("[/-]", "_", str)
662         return a
663 %%
664 parser Config:
665     ignore:                     r'\s+'
666     ignore:                     "#.*?\r?\n"
667
668     # less general tokens should come first, otherwise they get matched
669     # by the re's
670     token COMMENT:              'comment'
671     token CPU:                  'cpu'
672     token CPU_BUS:              'cpu_bus'
673     token CHIP:                 'chip'
674     token DEVICE:               'device'
675     token DEVICE_ID:            'device_id'
676     token DRQ:                  'drq'
677     token END:                  'end'
678     token EOF:                  '$'
679     token EQ:                   '='
680     token FORMAT:               'format'
681     token IO:                   'io'
682     token IRQ:                  'irq'
683     token MEM:                  'mem'
684     token NEVER:                'never'
685     token NONE:                 'none'
686     token PMC:                  'pmc'
687     token PRINT:                'print'
688     token REGISTER:             'register'
689     token VENDOR_ID:            'vendor_id'
690     token WRITE:                'write'
691     token NUM:                  '[0-9]+'
692     token HEX_NUM:              '[0-9a-fA-F]+'
693     token HEX_PREFIX:           '0x'
694     # Why is path separate? Because paths to resources have to at least
695     # have a slash, we thinks
696     token PATH:                 r'[-a-zA-Z0-9_.][-a-zA-Z0-9/_.]+[-a-zA-Z0-9_.]+'
697     # Dir's on the other hand are abitrary
698     # this may all be stupid.
699     token RULE:                 r'[-a-zA-Z0-9_$()./]+[-a-zA-Z0-9_ $()./]+[-a-zA-Z0-9_$()./]+'
700     token ID:                   r'[a-zA-Z_.]+[a-zA-Z0-9_.]*'
701     token STR:                  r'"([^\\"]+|\\.)*"'
702     token RAWTEXT:              r'.*'
703     token ON:                   'on'
704     token OFF:                  'off'
705     token PCI:                  'pci'
706     token PNP:                  'pnp'
707     token I2C:                  'i2c'
708     token APIC:                 'apic'
709     token APIC_CLUSTER:         'apic_cluster'
710     token CPU:                  'cpu'
711     token CPU_BUS:              'cpu_bus'
712     token PCI_DOMAIN:           'pci_domain'
713
714
715     rule expr:          logical                 {{ l = logical }}
716                         ( "&&" logical          {{ l = l and logical }}
717                         | "[|][|]" logical      {{ l = l or logical }}
718                         )*                      {{ return l }}
719
720     rule logical:       factor                  {{ n = factor }}
721                         ( "[+]" factor          {{ n = n+factor }}
722                         | "-"  factor           {{ n = n-factor }}
723                         )*                      {{ return n }}
724
725     rule factor:        term                    {{ v = term }}
726                         ( "[*]" term            {{ v = v*term }}
727                         | "/"  term             {{ v = v/term }}
728                         | "<<"  term            {{ v = v << term }}
729                         | ">=" term             {{ v = (v < term)}}
730                         )*                      {{ return v }}
731
732     # A term is a number, variable, or an expression surrounded by parentheses
733     rule term:          NUM                     {{ return long(NUM, 10) }}
734                 |       HEX_PREFIX HEX_NUM      {{ return long(HEX_NUM, 16) }}
735                 |       ID                      {{ return lookup(ID) }}
736                 |       unop                    {{ return unop }}
737                 |       "\\(" expr "\\)"        {{ return expr }}
738
739     rule unop:          "!" expr                {{ return not(expr) }}
740
741     rule partend<<C>>:  (stmt<<C>>)* END        {{ if (C): partpop()}}
742
743     # This is needed because the legacy cpu command could not distinguish
744     # between cpu vendors. It should just be PATH, but getting this change
745     # into the source tree will be tricky... 
746     # DO NOT USE ID AS IT MAY GO AWAY IN THE FUTURE
747     rule partid:        ID                      {{ return ID }}
748                 |       PATH                    {{ return PATH }}
749
750     rule parttype:      CHIP                    {{ return '' }}
751
752     rule partdef<<C>>:                          {{ name = 0 }} 
753                         parttype partid         
754                         [ STR                   {{ name = dequote(STR) }}
755                         ]                       {{ if (C): part(parttype, partid, 'Config.lb', name) }}
756                         partend<<C>>
757
758     rule field:         STR                     {{ return STR }}
759
760     rule register<<C>>: REGISTER field '=' STR  {{ if (C): addregister(field, STR) }}
761
762     rule enable<<C>>:                           {{ val = 1 }}
763                         ( ON                    {{ val = 1 }}
764                         | OFF                   {{ val = 0 }}
765                         )                       {{ if(C): partstack.tos().set_enabled(val) }}
766
767     rule resource<<C>>:                         {{ type = "" }}
768                         (  IO                   {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IO" }}
769                         |   MEM                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_MEM" }}
770                         |   IRQ                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IRQ" }}
771                         |   DRQ                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_DRQ" }}
772                         )
773                         term '='                {{ index = term }}
774                         term                    {{ value = term }}
775                                                 {{ if (C): partstack.tos().add_resource(type, index, value) }}
776     
777                              
778     rule resources<<C>>:                        {{ if (C): partstack.tos().start_resources() }}
779                         ( resource<<C>> )*
780                                                 {{ if (C): partstack.tos().end_resources() }}
781             
782     
783     rule pci<<C>>:      PCI                     {{ if (C): devicepart('pci') }}
784
785                         HEX_NUM                 {{ slot = int(HEX_NUM,16) }}
786                         '.' HEX_NUM             {{ function = int(HEX_NUM, 16) }}
787                                                 {{ if (C): partstack.tos().addpcipath(slot, function) }}
788     rule pci_domain<<C>>:       
789                         PCI_DOMAIN              {{ if (C): devicepart('pci_domain') }}
790                         HEX_NUM                 {{ pci_domain = int(HEX_NUM, 16) }}
791                                                 {{ if (C): partstack.tos().addpci_domainpath(pci_domain) }}
792
793     rule pnp<<C>>:      PNP                     {{ if (C): devicepart('pnp') }}
794                         HEX_NUM                 {{ port = int(HEX_NUM,16) }}
795                         '.' HEX_NUM             {{ device = int(HEX_NUM, 16) }}
796                                                 {{ if (C): partstack.tos().addpnppath(port, device) }}
797                                                 
798     rule i2c<<C>>:      I2C                     {{ if (C): devicepart('i2c') }}
799                         HEX_NUM                 {{ device = int(HEX_NUM, 16) }}
800                                                 {{ if (C): partstack.tos().addi2cpath(device) }}
801
802     rule apic<<C>>:     APIC                    {{ if (C): devicepart('apic') }}
803                         HEX_NUM                 {{ apic_id = int(HEX_NUM, 16) }}
804                                                 {{ if (C): partstack.tos().addapicpath(apic_id) }}
805
806     rule apic_cluster<<C>>: APIC_CLUSTER        {{ if (C): devicepart('apic_cluster') }}
807                         HEX_NUM                 {{ cluster = int(HEX_NUM, 16) }}
808                                                 {{ if (C): partstack.tos().addapic_clusterpath(cluster) }}
809
810     rule cpu<<C>>:      CPU                     {{ if (C): devicepart('cpu') }}
811                         HEX_NUM                 {{ id = int(HEX_NUM, 16) }}
812                                                 {{ if (C): partstack.tos().addcpupath(id) }}
813
814     rule cpu_bus<<C>>:  CPU_BUS                 {{ if (C): devicepart('cpu_bus') }}
815                         HEX_NUM                 {{ id = int(HEX_NUM, 16) }}
816                                                 {{ if (C): partstack.tos().addcpu_buspath(id) }}
817
818     rule dev_path<<C>>:
819                         pci<<C>>                {{ return pci }}
820                 |       pci_domain<<C>>         {{ return pci_domain }}
821                 |       pnp<<C>>                {{ return pnp }}
822                 |       i2c<<C>>                {{ return i2c }}
823                 |       apic<<C>>               {{ return apic }}
824                 |       apic_cluster<<C>>       {{ return apic_cluster }}
825                 |       cpu<<C>>                {{ return cpu }}
826                 |       cpu_bus<<C>>            {{ return cpu_bus }}
827                 
828     rule prtval:        expr                    {{ return str(expr) }}
829                 |       STR                     {{ return STR }}
830
831     rule prtlist:       prtval                  {{ el = "%(" + prtval }}
832                         ( "," prtval            {{ el = el + "," + prtval }}
833                         )*                      {{ return el + ")" }}   
834
835     rule prtstmt<<C>>:  PRINT STR               {{ val = STR }}
836                         [ "," prtlist           {{ val = val + prtlist }}
837                         ]                       {{ if (C): print eval(val) }}
838
839     rule device<<C>>:   DEVICE dev_path<<C>>
840                         enable<<C>>                     
841                         resources<<C>>
842                         partend<<C>> 
843
844     rule stmt<<C>>:
845                         partdef<<C>>            {{ return partdef }}
846                 |       prtstmt<<C>>            {{ return prtstmt }}
847                 |       register<<C>>           {{ return register }}
848                 |       device<<C>>             {{ return device }}
849
850     rule value:         STR                     {{ return dequote(STR) }} 
851                 |       expr                    {{ return expr }}
852
853     rule devicetree:    partdef<<1>>
854                         EOF                     {{ return 1 }}
855
856     rule wrstr<<ID>>:   STR                     {{ setwrite(ID, dequote(STR)) }}
857
858 %%
859
860 #=============================================================================
861 #               FILE OUTPUT 
862 #=============================================================================
863
864 def dumptree(part, lvl):
865         debug.info(debug.dumptree, "DUMPTREE ME is")
866         print "%s " % part
867         part.dumpme(lvl)
868         # dump the siblings -- actually are there any? not sure
869         # siblings are:
870         debug.info(debug.dumptree, "DUMPTREE SIBLINGS are")
871         kid = part.next_sibling
872         while (kid):
873                 kid.dumpme(lvl)
874                 kid = kid.next_sibling
875         # dump the kids
876         debug.info(debug.dumptree, "DUMPTREE KIDS are")
877         #for kid in part.children:
878         if (part.children):
879                 dumptree(part.children, lvl+1)
880         kid = part.next_sibling
881         while (kid):
882                 if (kid.children):
883                         dumptree(kid.children, lvl + 1)
884                 kid = kid.next_sibling
885         debug.info(debug.dumptree, "DONE DUMPTREE")
886
887 def writecode(image):
888         filename = os.path.join(img_dir, "static.c")
889         print "    SCONFIG    Creating", os.path.basename(filename)
890         file = safe_open(filename, 'w+')
891         file.write("#include <device/device.h>\n")
892         file.write("#include <device/pci.h>\n")
893         for path in image.getconfigincludes().values():
894                 file.write("#include \"%s\"\n" % path)
895         file.write("\n/* pass 0 */\n")
896         gencode(image.getroot(), file, 0)
897         file.write("\n/* pass 1 */\n")
898         gencode(image.getroot(), file, 1)
899         file.close()
900
901 def gencode(part, file, pass_num):
902         debug.info(debug.gencode, "GENCODE ME is")
903         part.gencode(file, pass_num)
904         # dump the siblings -- actually are there any? not sure
905         debug.info(debug.gencode, "GENCODE SIBLINGS are")
906         kid = part.next_sibling
907         while (kid):
908                 kid.gencode(file, pass_num)
909                 kid = kid.next_sibling
910         # now dump the children 
911         debug.info(debug.gencode, "GENCODE KIDS are")
912         if (part.children):
913                 gencode(part.children, file, pass_num)
914         kid = part.next_sibling
915         while (kid):
916                 if (kid.children):
917                         gencode(kid.children, file, pass_num)
918                 kid = kid.next_sibling
919         debug.info(debug.gencode, "DONE GENCODE")
920
921 def writegraph(image):
922         filename = os.path.join(img_dir, "static.dot")
923         print "    SCONFIG    Creating", os.path.basename(filename)
924         file = safe_open(filename, 'w+')
925         file.write("digraph devicetree {\n")
926         file.write("    rankdir=LR\n")
927         genranks(image.getroot(), file, 0)
928         gennodes(image.getroot(), file)
929         gengraph(image.getroot(), file)
930         file.write("}\n")
931         file.close()
932
933 def genranks(part, file, level):
934         #file.write("   # Level %d\n" % level )
935         file.write("    { rank = same; \"dev_%s_%d\"" % (part.type_name,part.instance ))
936         sib = part.next_sibling
937         while (sib):
938                 file.write("; \"dev_%s_%d\"" % (sib.type_name, sib.instance))
939                 sib = sib.next_sibling
940         file.write("}\n" )
941         # now dump the children 
942         if (part.children):
943                 genranks(part.children, file, level + 1)
944
945         kid = part.next_sibling
946         while (kid):
947                 if (kid.children):
948                         genranks(kid.children, file, level + 1)
949                 kid = kid.next_sibling
950
951
952 def gennodes(part, file):
953         file.write("    dev_%s_%d[shape=record, label=\"%s\"];\n" % (part.type_name,part.instance,part.graph_name() ))
954         sib = part.next_sibling
955         while (sib):
956                 file.write("    dev_%s_%d[shape=record, label=\"%s\"];\n" % (sib.type_name,sib.instance,sib.graph_name() ))
957                 sib = sib.next_sibling
958         # now dump the children
959         if (part.children):
960                 gennodes(part.children, file)
961
962         kid = part.next_sibling
963         while (kid):
964                 if (kid.children):
965                         gennodes(kid.children, file)
966                 kid = kid.next_sibling
967
968
969 def gengraph(part, file):
970         if (part.parent != part):
971                 file.write("    dev_%s_%d -> dev_%s_%d;\n" % \
972                                 (part.parent.type_name, part.parent.instance, \
973                                  part.type_name, part.instance ))
974         sib = part.next_sibling
975         while (sib):
976                 file.write("    dev_%s_%d -> dev_%s_%d;\n" % \
977                                 (sib.parent.type_name, sib.parent.instance, \
978                                  sib.type_name, sib.instance ))
979                 sib = sib.next_sibling
980
981         kid = part.next_sibling
982         while (kid):
983                 if (kid.children):
984                         gengraph(kid.children, file)
985                 kid = kid.next_sibling
986
987         if (part.children):
988                 gengraph(part.children, file)
989
990 #=============================================================================
991 #               MAIN PROGRAM
992 #=============================================================================
993 if __name__=='__main__':
994         from sys import argv
995         if (len(argv) < 4):
996                 fatal("Args: <file> <path to coreboot> <output-dir>")
997
998         file = "devicetree.cb"
999         partdir = os.path.join("mainboard", sys.argv[1])
1000         treetop = argv[2]
1001         srcdir = os.path.join(treetop, 'src')
1002         fulldir = os.path.join(srcdir, partdir)
1003         type_name = flatten_name(partdir)
1004         config_file = os.path.join(fulldir, file)
1005
1006         curimage = romimage("new")
1007         image = curimage
1008
1009         newpart = partobj(curimage, fulldir, partstack.tos(), 'mainboard', \
1010                 'mainboard', 0, 'chip')
1011        #print "Configuring PART %s, path %s" % (type, path)
1012         image.setroot(newpart);
1013         partstack.push(newpart)
1014
1015         fp = safe_open(config_file, 'r')
1016         if (not parse('devicetree', fp.read())):
1017                 fatal("Could not parse file")
1018         partstack.pop()
1019         
1020         img_dir = argv[3]
1021
1022         #debug.info(debug.dumptree, "DEVICE TREE:")
1023         #dumptree(curimage.getroot(), 0)
1024
1025         writecode(image)
1026         writegraph(image)
1027
1028         sys.exit(0)