coreboot-v2: drop this ugly historic union name in v2 that was dropped in v3
[coreboot.git] / util / newconfig / 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 target_dir = ''
14 target_name = ''
15 treetop = ''
16 full_mainboard_path = ''
17 mainboard_path = ''
18 global_options = {}
19 global_options_by_order = []
20 global_option_values = {}
21 global_uses_options = {}
22 global_exported_options = []
23 romimages = {}
24 buildroms = []
25 curimage = 0
26 alloptions = 0 # override uses at top level
27
28 local_path = re.compile(r'^\.')
29 include_pattern = re.compile(r'%%([^%]+)%%')
30
31 # the cpu type for this mainboard
32 cpu_type = 0
33
34 # -----------------------------------------------------------------------------
35 #                    Utility Classes
36 # -----------------------------------------------------------------------------
37
38 class stack:
39         """Used to keep track of the current part or dir"""
40         class __stack_iter:
41                 def __init__ (self, stack):
42                         self.index = 0
43                         self.len = len(stack)
44                         self.stack = stack
45
46                 def __iter__ (self):
47                         return self
48
49                 def next (self):
50                         if (self.index < self.len):
51                                 s = self.stack[self.index]
52                                 self.index = self.index + 1
53                                 return s
54                         raise StopIteration
55
56         def __init__ (self):
57                 self.stack = []
58
59         def __len__ (self):
60                 return len(self.stack)
61
62         def __getitem__ (self, i):
63                 return self.stack[i]
64
65         def __iter__ (self):
66                 return self.__stack_iter(self.stack)
67
68         def push(self, part):
69                 self.stack.append(part)
70
71         def pop(self):
72                 try:
73                         return self.stack.pop()
74                 except IndexError:
75                         return 0
76
77         def tos(self):
78                 try:
79                         return self.stack[-1]
80                 except IndexError:
81                         return 0
82
83         def empty(self):
84                 return (len(self.stack) == 0)
85 partstack = stack()
86 dirstack = stack()
87
88 class debug_info:
89         none = 0
90         gencode = 1
91         dumptree = 2
92         object = 3
93         dict = 4
94         statement = 5
95         dump = 6
96         gengraph = 7
97
98         def __init__(self, *level):
99                 self.__level = level
100
101         def setdebug(self, *level):
102                 self.__level = level
103
104         def level(self, level):
105                 return level in self.__level
106
107         def info(self, level, str):
108                 if level in self.__level:
109                         print str
110
111 global debug
112 debug = debug_info(debug_info.dumptree)
113 debug = debug_info(debug_info.object)
114
115 # -----------------------------------------------------------------------------
116 #                    Error Handling
117 # -----------------------------------------------------------------------------
118
119 class location:
120         """Used to keep track of our current location while parsing
121         configuration files"""
122         class __place:
123                 def __init__(self, file, line, command):
124                         self.file = file
125                         self.line = line
126                         self.command = command
127                 def next_line(self, command):
128                         self.line = self.line + 1
129                         self.command = command
130                 def at(self):
131                         return "%s:%d" % (self.file, self.line)
132         
133         def __init__ (self):
134                 self.stack = stack()
135
136         def __str__ (self):
137                 s = ''
138                 for p in self.stack:
139                         if (s == ''):
140                                 s = p.at()
141                         else:
142                                 s = s + '\n' + p.at()
143                 return s
144
145         def file(self):
146                 return self.stack.tos().file
147
148         def line(self):
149                 return self.stack.tos().line
150
151         def command(self):
152                 return self.stack.tos().command
153
154         def push(self, file):
155                 self.stack.push(self.__place(os.path.normpath(file), 0, ""))
156
157         def pop(self):
158                 self.stack.pop()
159
160         def next_line(self, command):
161                 self.stack.tos().next_line(command)
162
163         def at(self):
164                 return self.stack.tos().at()
165 loc = location()
166
167 def error(string):      
168         """Print error message"""
169         global errors, loc
170         errors = errors + 1
171         print "===> ERROR: %s" % string
172         print "%s" % loc
173
174 def fatal(string):      
175         """Print error message and exit"""
176         error(string)
177         exitiferrors()
178
179 def warning(string):
180         """Print warning message"""
181         global warnings, loc
182         warnings = warnings + 1
183         print "===> WARNING: %s" % string
184
185 def notice(string):
186         """Print notice message"""
187         #print "===> NOTE: %s" % string
188
189 def exitiferrors():
190         """Exit parser if an error has been encountered"""
191         if (errors != 0):
192                 sys.exit(1)
193
194 def safe_open(file, mode):
195         try:
196                 return open(file, mode)
197         except IOError:
198                 fatal("Could not open file \"%s\"" % file)
199
200 # -----------------------------------------------------------------------------
201 #                    Main classes
202 # -----------------------------------------------------------------------------
203
204 class romimage:
205         """A rom image is the ultimate goal of coreboot"""
206         def __init__ (self, name):
207                 # name of this rom image
208                 self.name = name
209
210                 # set by 'arch' directive
211                 self.arch = ''
212
213                 # set by 'payload' directive
214                 self.payload = ''
215
216                 # set by 'init' directive
217                 self.initfile = ''
218
219                 # make rules added by 'makerule' directive
220                 self.makebaserules = {}
221
222                 # object files added by 'object' directive
223                 self.objectrules = {}
224
225                 # init object files added by 'initobject' directive
226                 self.initobjectrules = {}
227
228                 # driver files added by 'driver' directive
229                 self.driverrules = {}
230
231                 # smm object files added by 'smmobject' directive
232                 self.smmobjectrules = {}
233
234                 # loader scripts added by 'ldscript' directive
235                 self.ldscripts = []
236
237                 # user defines added by 'makedefine' directive
238                 self.userdefines = []
239
240                 # files to be included in crt0.S
241                 self.initincludes = {}
242
243                 # as above, but order is preserved
244                 self.initincludesorder = []
245
246                 # transitional flag to support old crtinclude format
247                 self.useinitincludes = 0
248
249                 # instance counter for parts
250                 self.partinstance = 0
251
252                 # chip config files included by the 'config' directive
253                 self.configincludes = {}
254
255                 # root of part tree
256                 self.root = 0
257
258                 # name of target directory specified by 'target' directive
259                 self.target_dir = ''
260
261                 # option values used in rom image
262                 self.values = {}
263
264                 # exported options
265                 self.exported_options = []
266
267                 # Last device built
268                 self.last_device = 0
269
270         def getname(self):
271                 return self.name
272
273         def getvalues(self):
274                 return self.values
275
276         def setarch(self, arch):
277                 self.arch = arch
278
279         def setpayload(self, payload):
280                 self.payload = payload
281
282         def setinitfile(self, initfile):
283                 self.initfile = initfile
284
285         def getinitfile(self):
286                 return self.initfile
287
288         def addmakerule(self, id):
289                 o = getdict(self.makebaserules, id)
290                 if (o):
291                         warning("rule %s previously defined" % id)
292                 o = makerule(id)
293                 setdict(self.makebaserules, id, o)
294
295         def getmakerules(self):
296                 return self.makebaserules
297
298         def getmakerule(self, id):
299                 o = getdict(self.makebaserules, id)
300                 if (o):
301                         return o
302                 fatal("No such make rule \"%s\"" % id)
303
304         def addmakeaction(self, id, str):
305                 o = getdict(self.makebaserules, id)
306                 if (o):
307                         a = dequote(str)
308                         o.addaction(a)
309                         return
310                 fatal("No such rule \"%s\" for addmakeaction" % id)
311
312         def addmakedepend(self, id, str):
313                 o = getdict(self.makebaserules, id)
314                 if (o):
315                         a = dequote(str)
316                         o.adddependency(a)
317                         return
318                 fatal("No such rule \"%s\" for addmakedepend" % id)
319
320         # this is called with an an object name. 
321         # the easiest thing to do is add this object to the current 
322         # component.
323         # such kludgery. If the name starts with '.' then make the 
324         # dependency be on ./thing.x gag me.
325         def addobjectdriver(self, dict, object_name):
326                 global dirstack
327                 suffix = object_name[-2:]
328                 if (suffix == '.o'):
329                         suffix = '.c'
330                 base = object_name[:-2]
331                 type = object_name[-1:]
332                 if (object_name[0] == '.'):
333                         source = base + suffix
334                         object = base + '.o'
335                         rel_base = base
336                 else:
337                         rel_base = re.sub(treetop, "", os.path.join(dirstack.tos(), base))
338                         source = "$(TOP)/" + rel_base + suffix
339                         if (rel_base[0] == '/'):
340                                 rel_base = re.sub("^/", "", rel_base)
341                         object = rel_base + '.o'
342
343                 debug.info(debug.object, "add object %s source %s" % (object, source))
344                 l = getdict(dict, rel_base)
345                 if (l):
346                         warning("object/driver %s previously defined" % rel_base)
347                 setdict(dict, rel_base, [object, source, type, rel_base])
348
349         def addinitobjectrule(self, name):
350                 self.addobjectdriver(self.initobjectrules, name)
351
352         def addobjectrule(self, name):
353                 self.addobjectdriver(self.objectrules, name)
354
355         def adddriverrule(self, name):
356                 self.addobjectdriver(self.driverrules, name)
357
358         def addsmmobjectrule(self, name):
359                 self.addobjectdriver(self.smmobjectrules, name)
360
361         def getinitobjectrules(self):
362                 return self.initobjectrules
363
364         def getinitobjectrule(self, name):
365                 o = getdict(self.initobjectrules, name)
366                 if (o):
367                         return o
368                 fatal("No such init object rule \"%s\"" % name)
369
370         def getobjectrules(self):
371                 return self.objectrules
372
373         def getobjectrule(self, name):
374                 o = getdict(self.objectrules, name)
375                 if (o):
376                         return o
377                 fatal("No such object rule \"%s\"" % name)
378
379         def getdriverrules(self):
380                 return self.driverrules
381
382         def getdriverrule(self, name):
383                 o = getdict(self.driverrules, name)
384                 if (o):
385                         return o
386                 fatal("No such driver rule \"%s\"" % name)
387
388         def getsmmobjectrules(self):
389                 return self.smmobjectrules
390
391         def getsmmobjectrule(self, name):
392                 o = getdict(self.smmobjectrules, name)
393                 if (o):
394                         return o
395                 fatal("No such smm object rule \"%s\"" % name)
396
397         def addldscript(self, path):
398                 self.ldscripts.append(path)
399
400         def getldscripts(self):
401                 return self.ldscripts
402
403         def adduserdefine(self, str):
404                 self.userdefines.append(str)
405
406         def getuserdefines(self):
407                 return self.userdefines
408
409         def addinitinclude(self, str, path):
410                 if (str != 0):
411                         self.useinitincludes = 1
412
413                 debug.info(debug.object, "ADDCRT0: %s -> %s" % (str, path))
414                 o = getdict(self.initincludes, path)
415                 if (o):
416                         warning("init include for %s previously defined" % path)
417                 o = initinclude(str, path)
418                 setdict(self.initincludes, path, o)
419                 self.initincludesorder.append(path)
420
421         def getinitincludes(self):
422                 return self.initincludesorder
423
424         def getinitinclude(self, path):
425                 o = getdict(self.initincludes, path)
426                 if (o):
427                         return o
428                 fatal("No such init include \"%s\"" % path)
429
430         def addconfiginclude(self, part, path):
431                 setdict(self.configincludes, part, path)
432
433         def getconfigincludes(self):
434                 return self.configincludes
435
436         def getincludefilename(self):
437                 if (self.useinitincludes):
438                         return "crt0.S"
439                 else:
440                         return "crt0_includes.h"
441         
442         def newformat(self):
443                 return self.useinitincludes
444
445         def numparts(self):
446                 return self.partinstance
447
448         def newpartinstance(self):
449                 i = self.partinstance
450                 self.partinstance = self.partinstance + 1
451                 return i
452
453         def setroot(self, part):
454                 self.root = part
455
456         def getroot(self):
457                 return self.root
458
459         def settargetdir(self, path):
460                 self.targetdir = path
461
462         def gettargetdir(self):
463                 return self.targetdir
464
465 class buildrom:
466         """A buildrom statement"""
467         def __init__ (self, filename, size, roms):
468                 self.name = filename
469                 self.size = size
470                 self.roms = roms
471         
472         def __len__ (self):
473                 return len(self.roms)
474
475         def __getitem__(self,i):
476                 return self.roms[i]
477
478 class initinclude:
479         """include file for initialization code"""
480         def __init__ (self, str, path):
481                 self.string = str
482                 self.path = path
483
484         def getstring(self):
485                 return self.string
486
487         def getpath(self):
488                 return self.path
489
490 class makerule:
491         """Rule to be included in Makefile"""
492         def __init__ (self, target):
493                 self.target = target
494                 self.dependency = []
495                 self.actions = []
496
497         def addaction(self, action):
498                 self.actions.append(action)
499
500         def adddependency(self, dependency):
501                 self.dependency.append(dependency)
502
503         def gtarget(self):
504                 return self.target
505
506         def gdependency(self):
507                 return self.dependency
508
509         def gaction(self):
510                 return self.actions
511
512 class option:
513         """Configuration option"""
514         def __init__ (self, name):
515                 self.name = name        # name of option
516                 self.loc = 0            # current location
517                 self.used = 0           # option has been used
518                                         # it is undefined)
519                 self.comment = ''       # description of option
520                 self.exportable = 0     # option is able to be exported
521                 self.format = '%s'      # option print format
522                 self.write = []         # parts that can set this option
523
524         def where(self):
525                 return self.loc
526
527         def setcomment(self, comment, loc):
528                 if (self.comment != ''):
529                         print "%s: " % self.name
530                         print "Attempt to modify comment at %s" % loc 
531                         return
532                 self.comment = comment
533
534         def setexportable(self):
535                 self.exportable = 1
536
537         def setnoexport(self):
538                 self.exportable = 0
539
540         def setformat(self, fmt):
541                 self.format = fmt
542
543         def getformat(self):
544                 return self.format
545
546         def setused(self):
547                 if (self.exportable):
548                         self.exported = 1
549                 self.used = 1
550
551         def setwrite(self, part):
552                 self.write.append(part)
553
554         def isexportable(self):
555                 return self.exportable
556
557         def iswritable(self, part):
558                 return (part in self.write)
559
560 class option_value:
561         """Value of a configuration option. The option has a default
562         value which can be changed at any time. Once an option has been
563         set the default value is no longer used."""
564         def __init__(self, name, prev):
565                 self.name = name
566                 self.value = ''
567                 self.set = 0
568                 if (prev):
569                         self.value   = prev.value
570                         self.set     = prev.set
571                 
572
573         def setvalue(self, value):
574                 if ((self.set & 2) == 2):
575                         warning("Changing option %s" % self.name)
576                 else:
577                         self.set |= 2
578                 self.value = value
579
580         def setdefault(self, value):
581                 if ((self.set & 1) == 1):
582                         notice("Changing default value of %s" % self.name)
583                 
584                 if ((self.set & 2) == 0):
585                         self.value = value
586                         self.set |= 1
587
588         def contents(self):
589                 return self.value
590
591         def isset(self):
592                 return (self.set & 2) == 2
593
594
595 class partobj:
596         """A configuration part"""
597         def __init__ (self, image, dir, parent, part, type_name, instance_name, chip_or_device):
598                 debug.info(debug.object, "partobj dir %s parent %s part %s" \
599                                 % (dir, parent, part))
600
601                 # romimage that is configuring this part
602                 self.image = image
603
604                 # links for static device tree
605                 self.children = 0
606                 self.prev_sibling = 0
607                 self.next_sibling = 0
608                 self.prev_device = 0
609                 self.next_device = 0
610                 self.chip_or_device = chip_or_device
611
612                 # list of init code files
613                 self.initcode = []
614
615                 # initializers for static device tree
616                 self.registercode = {}
617
618                 # part name
619                 self.part = part
620
621                 # type name of this part
622                 self.type_name = type_name
623
624                 # object files needed to build this part
625                 self.objects = []
626
627                 # directory containg part files
628                 self.dir = dir
629
630                 # instance number, used to distinguish anonymous
631                 # instances of this part
632                 self.instance = image.newpartinstance()
633                 debug.info(debug.object, "INSTANCE %d" % self.instance)
634
635                 # Options used by this part
636                 self.uses_options = {}
637
638                 # Name of chip config file (0 if not needed)
639                 self.chipconfig = 0
640
641                 # Flag to indicate that we have generated type
642                 # definitions for this part (only want to do it once)
643                 self.done_types = 0
644
645                 # Path to the device
646                 self.path = ""
647
648                 # Resources of the device
649                 self.resoruce = ""
650                 self.resources = 0
651
652                 # Enabled state of the device
653                 self.enabled = 1
654
655                 # Flag if I am a dumplicate device
656                 self.dup = 0
657
658                 # If no instance name is supplied then generate
659                 # a unique name
660                 if (instance_name == 0):
661                         self.instance_name = self.type_name + \
662                                         "_dev%d" % self.instance
663                         self.chipinfo_name = "%s_info_%d" \
664                                         % (self.type_name, self.instance)
665                 else:
666                         self.instance_name = instance_name
667                         self.chipinfo_name = "%s_info_%d" % (self.instance_name, self.instance)
668
669                 # Link this part into the device list
670                 if (self.chip_or_device == 'device'):
671                         if (image.last_device):
672                                 image.last_device.next_device = self
673                         self.prev_device = image.last_device
674                         image.last_device = self
675
676                 # Link this part into the tree
677                 if (parent and (part != 'arch')):
678                         debug.info(debug.gencode, "add to parent")
679                         self.parent   = parent
680                         # add current child as my sibling, 
681                         # me as the child.
682                         if (parent.children):
683                                 debug.info(debug.gencode, "add %s (%d) as sibling" % (parent.children.dir, parent.children.instance))
684                                 youngest = parent.children
685                                 while(youngest.next_sibling):
686                                         youngest = youngest.next_sibling
687                                 youngest.next_sibling = self
688                                 self.prev_sibling = youngest
689                         else:
690                                 parent.children = self
691                 else:
692                         self.parent = self
693
694
695         def info(self):
696                 return "%s: %s" % (self.part, self.type)
697         def type(self):
698                 return self.chip_or_device
699
700         def readable_name(self):
701                 name = ""
702                 name = "%s_%d" % (self.type_name, self.instance)
703                 if (self.chip_or_device == 'chip'):
704                         name = "%s %s %s" % (name, self.part, self.dir)
705                 else:
706                         name = "%s %s" % (name, self.path)
707                 return name
708
709         def graph_name(self):
710                 name = "{ {_dev%d|" % self.instance
711                 if (self.part):
712                         name = "%s%s" % (name, self.part)
713                 else:
714                         name = "%s%s" % (name, self.chip_or_device)
715                 if (self.type_name):
716                         name = "%s}|%s}" % (name, self.type_name)
717                 else:
718                         name = "%s}|%s}" % (name, self.parent.type_name)
719                 return name
720                         
721         def dumpme(self, lvl):
722                 """Dump information about this part for debugging"""
723                 print "%d: %s" % (lvl, self.readable_name())
724                 print "%d: part %s" % (lvl, self.part)
725                 print "%d: instance %d" % (lvl, self.instance)
726                 print "%d: chip_or_device %s"  %  (lvl, self.chip_or_device)
727                 print "%d: dir %s" % (lvl,self.dir)
728                 print "%d: type_name %s" % (lvl,self.type_name)
729                 print "%d: parent: %s" % (lvl, self.parent.readable_name())
730                 if (self.children):
731                         print "%d: child %s" % (lvl, self.children.readable_name())
732                 if (self.next_sibling):
733                         print "%d: siblings %s" % (lvl, self.next_sibling.readable_name())
734                 print "%d: initcode " % lvl
735                 for i in self.initcode:
736                         print "\t%s" % i
737                 print "%d: registercode " % lvl
738                 for f, v in self.registercode.items():
739                         print "\t%s = %s" % (f, v)
740                 print "\n"
741
742         def firstchilddevice(self):
743                 """Find the first device in the children link."""
744                 kid = self.children
745                 while (kid):
746                         if (kid.chip_or_device == 'device'):
747                                 return kid
748                         else:
749                                 kid = kid.children
750                 return 0
751
752         def firstparentdevice(self):
753                 """Find the first device in the parent link."""
754                 parent = self.parent
755                 while (parent and (parent.parent != parent) and (parent.chip_or_device != 'device')):
756                         parent = parent.parent
757                 if ((parent.parent != parent) and (parent.chip_or_device != 'device')):
758                         parent = 0
759                 while(parent and (parent.dup == 1)):
760                         parent = parent.prev_sibling
761                 if (not parent):
762                         fatal("Device %s has no device parent; this is a config file error" % self.readable_name())
763                 return parent
764
765         def firstparentdevicelink(self):
766                 """Find the first device in the parent link and record which link it is."""
767                 link = 0
768                 parent = self.parent
769                 while (parent and (parent.parent != parent) and (parent.chip_or_device != 'device')):
770                         parent = parent.parent
771                 if ((parent.parent != parent) and (parent.chip_or_device != 'device')):
772                         parent = 0
773                 while(parent and (parent.dup == 1)):
774                         parent = parent.prev_sibling
775                         link = link + 1
776                 if (not parent):
777                         fatal("Device %s has no device parent; this is a config file error" % self.readable_name())
778                 return link
779
780
781         def firstparentchip(self):
782                 """Find the first chip in the parent link."""
783                 parent = self.parent
784                 while (parent):
785                         if ((parent.parent == parent) or (parent.chip_or_device == 'chip')):
786                                 return parent
787                         else:
788                                 parent = parent.parent
789                 fatal("Device %s has no chip parent; this is a config file error" % self.readable_name())
790
791         def firstsiblingdevice(self):
792                 """Find the first device in the sibling link."""
793                 sibling = self.next_sibling
794                 while(sibling and (sibling.path == self.path)):
795                         sibling = sibling.next_sibling
796                 if ((not sibling) and (self.parent.chip_or_device == 'chip')):
797                         sibling = self.parent.next_sibling
798                 while(sibling):
799                         if (sibling.chip_or_device == 'device'):
800                                 return sibling
801                         else:
802                                 sibling = sibling.children
803                 return 0
804
805         def gencode(self, file, pass_num):
806                 """Generate static initalizer code for this part. Two passes
807                 are used - the first generates type information, and the second
808                 generates instance information"""
809                 if (pass_num == 0):
810                         if (self.chip_or_device == 'chip'):
811                                 return;
812                         else:
813                                 if (self.instance):
814                                         file.write("struct device %s;\n" \
815                                                 % self.instance_name)
816                                 else:
817                                         file.write("struct device dev_root;\n")
818                         return
819                 # This is pass the second, which is pass number 1
820                 # this is really just a case statement ...
821
822                 if (self.chip_or_device == 'chip'):
823                         if (self.chipconfig):
824                                 debug.info(debug.gencode, "gencode: chipconfig(%d)" % \
825                                         self.instance)
826                                 file.write("struct %s_config %s" % (self.type_name ,\
827                                         self.chipinfo_name))
828                                 if (self.registercode):
829                                         file.write("\t= {\n")
830                                         for f, v in self.registercode.items():
831                                                 file.write( "\t.%s = %s,\n" % (f, v))
832                                         file.write("};\n")
833                                 else:
834                                         file.write(";")
835                                 file.write("\n")
836
837                         if (self.instance == 0):
838                                 self.instance_name = "dev_root"
839                                 file.write("struct device **last_dev_p = &%s.next;\n" % (self.image.last_device.instance_name))
840                                 file.write("struct device dev_root = {\n")
841                                 file.write("\t.ops = &default_dev_ops_root,\n")
842                                 file.write("\t.bus = &dev_root.link[0],\n")
843                                 file.write("\t.path = { .type = DEVICE_PATH_ROOT },\n")
844                                 file.write("\t.enabled = 1,\n\t.links = 1,\n")
845                                 file.write("\t.on_mainboard = 1,\n")
846                                 file.write("\t.link = {\n\t\t[0] = {\n")
847                                 file.write("\t\t\t.dev=&dev_root,\n\t\t\t.link = 0,\n")
848                                 file.write("\t\t\t.children = &%s,\n" % self.firstchilddevice().instance_name)
849                                 file.write("\t\t},\n")
850                                 file.write("\t},\n")
851                                 if (self.chipconfig):
852                                         file.write("\t.chip_ops = &%s_ops,\n" % self.type_name)
853                                         file.write("\t.chip_info = &%s_info_%s,\n" % (self.type_name, self.instance))
854                                 file.write("\t.next = &%s,\n" % self.firstchilddevice().instance_name)
855                                 file.write("};\n")
856                         return
857
858                 # Don't print duplicate devices, just print their children
859                 if (self.dup):
860                         return
861
862                 file.write("struct device %s = {\n" % self.instance_name)
863                 file.write("\t.ops = 0,\n")
864                 file.write("\t.bus = &%s.link[%d],\n" % \
865                         (self.firstparentdevice().instance_name, \
866                         self.firstparentdevicelink()))
867                 file.write("\t.path = {%s},\n" % self.path)
868                 file.write("\t.enabled = %d,\n" % self.enabled)
869                 file.write("\t.on_mainboard = 1,\n")
870                 if (self.resources):
871                         file.write("\t.resources = %d,\n" % self.resources)
872                         file.write("\t.resource = {%s\n\t },\n" % self.resource)
873                 file.write("\t.link = {\n");    
874                 links = 0
875                 bus = self
876                 while(bus and (bus.path == self.path)):
877                         child = bus.firstchilddevice()
878                         if (child or (bus != self) or (bus.next_sibling and (bus.next_sibling.path == self.path))):
879                                 file.write("\t\t[%d] = {\n" % links)
880                                 file.write("\t\t\t.link = %d,\n" % links)
881                                 file.write("\t\t\t.dev = &%s,\n" % self.instance_name)
882                                 if (child):
883                                         file.write("\t\t\t.children = &%s,\n" %child.instance_name)
884                                 file.write("\t\t},\n")
885                                 links = links + 1
886                         if (1): 
887                                 bus = bus.next_sibling
888                         else:
889                                 bus = 0
890                 file.write("\t},\n")
891                 file.write("\t.links = %d,\n" % (links))
892                 sibling = self.firstsiblingdevice(); 
893                 if (sibling):
894                         file.write("\t.sibling = &%s,\n" % sibling.instance_name)
895                 chip = self.firstparentchip()
896                 if (chip and chip.chipconfig):
897                         file.write("\t.chip_ops = &%s_ops,\n" % chip.type_name)
898                         file.write("\t.chip_info = &%s_info_%s,\n" % (chip.type_name, chip.instance))
899                 if (self.next_device):  
900                         file.write("\t.next=&%s\n" % self.next_device.instance_name)
901                 file.write("};\n")
902                 return
903
904         def addinit(self, code):
905                 """Add init file to this part"""
906                 self.initcode.append(code)
907                 
908         def addconfig(self, path):
909                 """Add chip config file to this part"""
910                 self.chipconfig = os.path.join(self.dir, path)
911                 self.image.addconfiginclude(self.type_name, self.chipconfig)
912
913         def addregister(self, field, value):
914                 """Register static initialization information"""
915                 if (self.chip_or_device != 'chip'):
916                         fatal("Only chips can have register values")
917                 field = dequote(field)
918                 value = dequote(value)
919                 setdict(self.registercode, field, value)
920
921         def set_enabled(self, enabled):
922                 self.enabled = enabled
923
924         def start_resources(self):
925                 self.resource = ""
926                 self.resources = 0
927
928         def end_resources(self):
929                 self.resource = "%s" % (self.resource)
930
931         def add_resource(self, type, index, value):
932                 """ Add a resource to a device """
933                 self.resource = "%s\n\t\t{ .flags=%s, .index=0x%x, .base=0x%x}," % (self.resource, type, index, value)
934                 self.resources = self.resources + 1
935
936         def set_path(self, path):
937                 self.path = path
938                 if (self.prev_sibling and (self.prev_sibling.path == self.path)):
939                         self.dup = 1
940                         if (self.prev_device):
941                                 self.prev_device.next_device = self.next_device
942                         if (self.next_device):  
943                                 self.next_device.prev_device = self.prev_device
944                         if (self.image.last_device == self):
945                                 self.image.last_device = self.prev_device
946                         self.prev_device = 0
947                         self.next_device = 0
948                 
949         def addpcipath(self, slot, function):
950                 """ Add a relative pci style path from our parent to this device """
951                 if ((slot < 0) or (slot > 0x1f)):
952                         fatal("Invalid device id")
953                 if ((function < 0) or (function > 7)):
954                         fatal("Invalid pci function %s" % function )
955                 self.set_path(".type=DEVICE_PATH_PCI,{.pci={ .devfn = PCI_DEVFN(0x%x,%d)}}" % (slot, function))
956
957         def addpnppath(self, port, device):
958                 """ Add a relative path to a pnp device hanging off our parent """
959                 if ((port < 0) or (port > 65536)):
960                         fatal("Invalid port")
961                 if ((device < 0) or (device > 0xffff)):
962                         fatal("Invalid device")
963                 self.set_path(".type=DEVICE_PATH_PNP,{.pnp={ .port = 0x%x, .device = 0x%x }}" % (port, device))
964                 
965         def addi2cpath(self, device):
966                 """ Add a relative path to a i2c device hanging off our parent """
967                 if ((device < 0) or (device > 0x7f)):
968                         fatal("Invalid device")
969                 self.set_path(".type=DEVICE_PATH_I2C,{.i2c={ .device = 0x%x }}" % (device))
970
971         def addapicpath(self, apic_id):
972                 """ Add a relative path to a cpu device hanging off our parent """
973                 if ((apic_id < 0) or (apic_id > 255)):
974                         fatal("Invalid device")
975                 self.set_path(".type=DEVICE_PATH_APIC,{.apic={ .apic_id = 0x%x }}" % (apic_id))
976     
977         def addpci_domainpath(self, pci_domain):
978                 """ Add a pci_domain number to a chip """
979                 if ((pci_domain < 0) or (pci_domain > 0xffff)):
980                         fatal("Invalid pci_domain: 0x%x is out of the range 0 to 0xffff" % pci_domain)
981                 self.set_path(".type=DEVICE_PATH_PCI_DOMAIN,{.pci_domain={ .domain = 0x%x }}" % (pci_domain))
982     
983         def addapic_clusterpath(self, cluster):
984                 """ Add an apic cluster to a chip """
985                 if ((cluster < 0) or (cluster > 15)):
986                         fatal("Invalid apic cluster: %d is out of the range 0 to ff" % cluster)
987                 self.set_path(".type=DEVICE_PATH_APIC_CLUSTER,{.apic_cluster={ .cluster = 0x%x }}" % (cluster))
988     
989         def addcpupath(self, cpu_id):
990                 """ Add a relative path to a cpu device hanging off our parent """
991                 if ((cpu_id < 0) or (cpu_id > 255)):
992                         fatal("Invalid device")
993                 self.set_path(".type=DEVICE_PATH_CPU,{.cpu={ .id = 0x%x }}" % (cpu_id))
994     
995
996         def addcpu_buspath(self, id):
997                 """ Add a cpu_bus to a chip """
998                 if ((id < 0) or (id > 255)):
999                         fatal("Invalid device")
1000                 self.set_path(".type=DEVICE_PATH_CPU_BUS,{.cpu_bus={ .id = 0x%x }}" % (id))
1001     
1002         def usesoption(self, name):
1003                 """Declare option that can be used by this part"""
1004                 global global_options
1005                 o = getdict(global_options, name)
1006                 if (o == 0):
1007                         fatal("can't use undefined option %s" % name)
1008                 o1 = getdict(self.uses_options, name)
1009                 if (o1):
1010                         return
1011                 setdict(self.uses_options, name, o)
1012                 exportoption(o, self.image.exported_options)
1013
1014 # -----------------------------------------------------------------------------
1015 #                    statements 
1016 # -----------------------------------------------------------------------------
1017
1018 def getdict(dict, name):
1019         if name not in dict.keys(): 
1020                 debug.info(debug.dict, "Undefined: %s" % name)
1021                 return 0
1022         v = dict.get(name, 0)
1023         debug.info(debug.dict, "getdict %s returning %s" % (name, v))
1024         return v
1025
1026 def setdict(dict, name, value):
1027         debug.info(debug.dict, "setdict sets %s to %s" % (name, value))
1028         if name in dict.keys():
1029                 print "Duplicate in dict: %s" % name
1030         dict[name] = value
1031
1032 # options. 
1033 # to create an option, it has to not exist. 
1034 # When an option value is fetched, the fact that it was used is 
1035 # remembered. 
1036 # Legal things to do:
1037 # set a default value, then set a real value before the option is used.
1038 # set a value, try to set a default, default silently fails.
1039 # Illegal:
1040 # use the value, then try to set the value
1041
1042 def newoption(name):
1043         global global_options, global_options_by_order
1044         o = getdict(global_options, name)
1045         if (o):
1046                 fatal("option %s already defined" % name)
1047         o = option(name)
1048         setdict(global_options, name, o)
1049         global_options_by_order.append(name)
1050
1051 def newoptionvalue(name, image):
1052         g = getdict(global_option_values, name)
1053         v = option_value(name, g)
1054         if (image):
1055                 setdict(image.getvalues(), name, v)
1056         else:
1057                 setdict(global_option_values, name, v)
1058         return v
1059
1060 def getoptionvalue(name, op, image):
1061         global global_option_values
1062         #print "getoptionvalue name %s op %s image %s\n" % (name, op,image)
1063         if (op == 0):
1064                 # we want to debug config files, not the config tool, so no:
1065                 # print_stack() 
1066                 fatal("Option %s undefined (missing use command?)" % name)
1067         if (image):
1068                 v = getdict(image.getvalues(), name)
1069         else:
1070                 v = getdict(global_option_values, name)
1071         return v
1072
1073 def getoption(name, image):
1074         """option must be declared before being used in a part
1075         if we're not processing a part, then we must
1076         be at the top level where all options are available"""
1077
1078         global global_uses_options, alloptions, curimage
1079
1080         #print "getoption: name %s image %s alloptions %s curimage %s\n\n" % (name, image, alloptions, curimage)
1081         curpart = partstack.tos()
1082         if (alloptions):
1083                 o = getdict(global_options, name)
1084         elif (curpart):
1085                 o = getdict(curpart.uses_options, name)
1086                 if (o == 0):
1087                         print "curpart.uses_options is %s\n" % curpart.uses_options
1088         else:
1089                 o = getdict(global_uses_options, name)
1090         v = getoptionvalue(name, o, image)
1091         if (v == 0):
1092                 v = getoptionvalue(name, o, 0)
1093         if (v == 0):
1094                 fatal("No value for option %s" % name)
1095         val = v.contents()
1096         if (not (type(val) is types.StringType)):
1097                 return v.contents()
1098         if (val == '' or val[0] != '{'):
1099                 return v.contents()
1100         s = curimage
1101         curimage = image
1102         val = parse('delexpr', val)
1103         curimage = s
1104         exitiferrors()
1105         return val
1106
1107 def setoption(name, value, imp):
1108         """Set an option from within a configuration file. Normally this
1109         is only permitted in the target (top level) configuration file.
1110         If 'imp' is true, then set an option implicitly (e.g. 'arch' 
1111         and 'mainboard' statements). Implicit options can be set anywhere 
1112         the statements are legal, but also performs an implicit 'uses' 
1113         for the option"""
1114
1115         global loc, global_options, global_option_values, curimage
1116
1117         curpart = partstack.tos()
1118         if (not imp and curpart):
1119                 fatal("Options may only be set in target configuration file")
1120         if (imp):
1121                 usesoption(name)
1122         if (curpart):
1123                 o = getdict(curpart.uses_options, name)
1124         else:
1125                 o = getdict(global_uses_options, name)
1126         if (not o):
1127                 fatal("Attempt to set nonexistent option %s (missing USES?)" % name)
1128         v = getoptionvalue(name, o, curimage)
1129         if (v == 0):
1130                 v = newoptionvalue(name, curimage)
1131         v.setvalue(value)
1132
1133 def exportoption(op, exported_options):
1134         if (not op.isexportable()):
1135                 return
1136         if (not op in exported_options):
1137                 exported_options.append(op)
1138
1139 def setdefault(name, value, isdef):
1140         """Set the default value of an option from within a configuration 
1141         file. This is permitted from any configuration file, but will
1142         result in a warning if the default is set more than once.
1143         If 'isdef' is set, we're defining the option in Options.lb so
1144         there is no need for 'uses'."""
1145
1146         global loc, global_options, curimage
1147
1148         if (isdef):
1149                 o = getdict(global_options, name)
1150                 if (not o):
1151                         return
1152                 image = 0
1153         else:
1154                 curpart = partstack.tos()
1155                 if (curpart):
1156                         o = getdict(curpart.uses_options, name)
1157                 else:
1158                         o = getdict(global_uses_options, name)
1159                 if (not o):
1160                         fatal("Attempt to set default for nonexistent option %s (missing USES?)" % name)
1161                 image = curimage
1162
1163         v = getoptionvalue(name, o, image)
1164         if (v == 0):
1165                 v = newoptionvalue(name, image)
1166         v.setdefault(value)
1167
1168 def setnodefault(name):
1169         global loc, global_options
1170         o = getdict(global_options, name)
1171         if (not o):
1172                 return
1173         v = getdict(global_option_values, name)
1174         if (v != 0):
1175                 warning("removing default for %s" % name)
1176                 del global_option_values[name]
1177
1178 def setcomment(name, value):
1179         global loc, global_options
1180         o = getdict(global_options, name)
1181         if (not o):
1182                 fatal("setcomment: %s not here" % name)
1183         o.setcomment(value, loc)
1184
1185 def setexported(name):
1186         global global_options
1187         o = getdict(global_options, name)
1188         if (not o):
1189                 fatal("setexported: %s not here" % name)
1190         o.setexportable()
1191         global_exported_options.append(o)
1192
1193 def setnoexport(name):
1194         global global_options
1195         o = getdict(global_options, name)
1196         if (not o):
1197                 fatal("setnoexport: %s not here" % name)
1198         o.setnoexport()
1199         if (o in global_exported_options):
1200                 global_exported_options.remove(o)
1201
1202 def setexportable(name):
1203         global global_options
1204         o = getdict(global_options, name)
1205         if (not o):
1206                 fatal("setexportable: %s not here" % name)
1207         o.setexportable()
1208
1209 def setformat(name, fmt):
1210         global global_options
1211         o = getdict(global_options, name)
1212         if (not o):
1213                 fatal("setformat: %s not here" % name)
1214         o.setformat(fmt)
1215
1216 def getformated(name, image):
1217         global global_options, global_option_values
1218         o = getdict(global_options, name)
1219         v = getoption(name, image)
1220         f = o.getformat()
1221         return (f % v)
1222
1223 def setwrite(name, part):
1224         global global_options
1225         o = getdict(global_options, name)
1226         if (not o):
1227                 fatal("setwrite: %s not here" % name)
1228         o.setwrite(part)
1229
1230 def hasvalue(name, image):
1231         global global_options
1232         o = getdict(global_options, name)
1233         if (o == 0):
1234                 return 0
1235         v = 0
1236         if (image):
1237                 v = getdict(image.getvalues(), name)
1238         if (v == 0):
1239                 v = getdict(global_option_values, name)
1240         return (v != 0)
1241
1242 def isset(name, part):
1243         global global_uses_options, global_option_values, curimage
1244         if (part):
1245                 o = getdict(part.uses_options, name)
1246         else:
1247                 o = getdict(global_uses_options, name)
1248         if (o == 0):
1249                 return 0
1250         v = 0
1251         if (curimage):
1252                 v = getdict(curimage.getvalues(), name)
1253         if (v == 0):
1254                 v = getdict(global_option_values, name)
1255         return (v != 0 and v.isset())
1256
1257 def usesoption(name):
1258         global global_options, global_uses_options
1259         curpart = partstack.tos()
1260         if (curpart):
1261                 curpart.usesoption(name)
1262                 return
1263         o = getdict(global_options, name)
1264         if (o == 0):
1265                 fatal("Can't use undefined option %s" % name)
1266         o1 = getdict(global_uses_options, name)
1267         if (o1):
1268                 return
1269         setdict(global_uses_options, name, o)
1270         exportoption(o, global_exported_options)
1271
1272 def validdef(name, defval):
1273         global global_options
1274         o = getdict(global_options, name)
1275         if (not o):
1276                 fatal("validdef: %s not here" % name)
1277         if ((defval & 1) != 1):
1278             fatal("Must specify default value for option %s" % name)
1279         if ((defval & 2) != 2):
1280             fatal("Must specify export for option %s" % name)
1281         if ((defval & 4) != 4):
1282             fatal("Must specify comment for option %s" % name)
1283
1284 def loadoptions(path, file, rule):
1285         file = os.path.join('src', path, file)
1286         optionsfile = os.path.join(treetop, file)
1287         fp = safe_open(optionsfile, 'r')
1288         loc.push(file)
1289         if (not parse(rule, fp.read())):
1290                 fatal("Could not parse file")
1291         loc.pop()
1292
1293 def addinit(path):
1294         global curimage, dirstack
1295         if (path[0] == '/'):
1296                 curimage.setinitfile(treetop + '/src/' + path)
1297         else:
1298                 curimage.setinitfile(dirstack.tos() + '/' + path)
1299         print "Adding init file: %s" % path
1300
1301 def addconfig(path):
1302         global partstack
1303         curpart = partstack.tos()
1304         curpart.addconfig(path)
1305
1306 def addregister(field, value):
1307         global partstack
1308         curpart = partstack.tos()
1309         curpart.addregister(field, value)
1310
1311 def addcrt0include(path):
1312         """we do the crt0include as a dictionary, so that if needed we
1313         can trace who added what when. Also it makes the keys
1314         nice and unique."""
1315         global curimage
1316         curimage.addinitinclude(0, path)
1317
1318 def addinitinclude(str, path):
1319         global curimage
1320         curimage.addinitinclude(dequote(str), path)
1321
1322 def addldscript(path):
1323         global curimage, dirstack
1324         curdir = dirstack.tos()
1325         if (path[0] == '/'):
1326                 fullpath =  treetop + '/src/' + path
1327         else:
1328                 fullpath = curdir + '/' + path
1329         debug.info(debug.statement, "fullpath :%s: curdir :%s: path :%s:" % (fullpath, curdir, path))
1330         curimage.addldscript(fullpath)
1331
1332 def payload(path):
1333         global curimage
1334         curimage.setpayload(path)
1335         adduserdefine("PAYLOAD:=%s"%path)
1336
1337 def startromimage(name):
1338         global romimages, curimage, target_dir, target_name
1339         curpart = partstack.tos()
1340         print "Configuring ROMIMAGE %s Curimage %s" % (name, curimage)
1341         print "Curpart is %s\n" % curpart
1342         o = getdict(romimages, name)
1343         if (o):
1344                 fatal("romimage %s previously defined" % name)
1345         curimage = romimage(name)
1346         curimage.settargetdir(os.path.join(target_dir, name))
1347         #o = partobj(curimage, target_dir, 0, 'board', target_name)
1348         #curimage.setroot(o)
1349         setdict(romimages, name, curimage)
1350         dodir('/config', 'Config.lb')
1351
1352 def endromimage():
1353         global curimage
1354         mainboard()
1355         print "End ROMIMAGE"
1356         curimage = 0
1357         #curpart = 0
1358
1359 def mainboardsetup(path):
1360         global full_mainboard_path, mainboard_path
1361         mainboard_path = os.path.join('mainboard', path)
1362         loadoptions(mainboard_path, 'Options.lb', 'mainboardvariables')
1363         full_mainboard_path = os.path.join(treetop, 'src', 'mainboard', path)
1364         vendor = re.sub("/.*", "", path)
1365         part_number = re.sub("[^/]*/", "", path)
1366         setdefault('MAINBOARD', full_mainboard_path, 0)
1367         setdefault('MAINBOARD_VENDOR', vendor, 0)
1368         setdefault('MAINBOARD_PART_NUMBER', part_number, 0)
1369
1370 def mainboard():
1371         global curimage, dirstack, partstack
1372         file = 'Config.lb'
1373         partdir = mainboard_path
1374         srcdir = os.path.join(treetop, 'src')
1375         fulldir = os.path.join(srcdir, partdir)
1376         type_name = flatten_name(partdir)
1377         newpart = partobj(curimage, fulldir, partstack.tos(), 'mainboard', \
1378                 'mainboard', 0, 'chip')
1379         #print "Configuring PART %s" % (type)
1380         partstack.push(newpart)
1381         #print "  new PART tos is now %s\n" %partstack.tos().info()
1382         dirstack.push(fulldir)
1383         loadoptions(mainboard_path, 'Options.lb', 'mainboardvariables')
1384         # special case for 'cpu' parts.
1385         # we could add a new function too, but this is rather trivial.
1386         # if the part is a cpu, and we haven't seen it before,
1387         # arrange to source the directory /cpu/'type'
1388         doconfigfile(srcdir, partdir, file, 'cfgfile')
1389         curimage.setroot(partstack.tos())
1390         partpop()
1391
1392 def addbuildrom(filename, size, roms):
1393         global buildroms
1394         print "Build ROM size %d" % size
1395         b = buildrom(filename, size, roms)
1396         buildroms.append(b)
1397
1398 def addinitobject(object_name):
1399         global curimage
1400         curimage.addinitobjectrule(object_name)
1401
1402 def addobject(object_name):
1403         global curimage
1404         curimage.addobjectrule(object_name)
1405
1406 def adddriver(driver_name):
1407         global curimage
1408         curimage.adddriverrule(driver_name)
1409
1410 def addsmmobject(object_name):
1411         global curimage
1412         curimage.addsmmobjectrule(object_name)
1413
1414 def target(name):
1415         global target_dir, target_name
1416         print "Configuring TARGET %s" % name
1417         target_name = name
1418         target_dir = os.path.join(os.path.dirname(loc.file()), name)
1419         if not os.path.isdir(target_dir):
1420                 print "Creating directory %s" % target_dir
1421                 os.makedirs(target_dir)
1422         print "Will place Makefile, crt0.S, etc. in %s" % target_dir
1423
1424
1425 def cpudir(path):
1426         global cpu_type
1427         if (cpu_type and (cpu_type != path)):
1428                 fatal("Two different CPU types: %s and %s" % (cpu_type, path))
1429         srcdir = "/cpu/%s" % path
1430         dodir(srcdir, "Config.lb")
1431         cpu_type = path
1432         
1433 def devicepart(type):
1434         global curimage, dirstack, partstack
1435         newpart = partobj(curimage, 0, partstack.tos(), type, \
1436                         '', 0, 'device')
1437         #print "Configuring PART %s" % (type)
1438         partstack.push(newpart)
1439         #print "  new PART tos is now %s\n" %partstack.tos().info()
1440         # just push TOS, so that we can pop later. 
1441         dirstack.push(dirstack.tos())
1442         
1443 def part(type, path, file, name):
1444         global curimage, dirstack, partstack
1445         partdir = os.path.join(type, path)
1446         srcdir = os.path.join(treetop, 'src')
1447         fulldir = os.path.join(srcdir, partdir)
1448         type_name = flatten_name(partdir)
1449         newpart = partobj(curimage, fulldir, partstack.tos(), type, \
1450                         type_name, name, 'chip')
1451         #print "Configuring PART %s, path %s" % (type, path)
1452         partstack.push(newpart)
1453         #print "  new PART tos is now %s\n" %partstack.tos().info()
1454         dirstack.push(fulldir)
1455         # special case for 'cpu' parts. 
1456         # we could add a new function too, but this is rather trivial.
1457         # if the part is a cpu, and we haven't seen it before, 
1458         # arrange to source the directory /cpu/'type'
1459         if (type == 'cpu'):
1460                 cpudir(path)
1461         else:
1462                 doconfigfile(srcdir, partdir, file, 'cfgfile')
1463
1464 def partpop():
1465         global dirstack, partstack
1466         curpart = partstack.tos()
1467         if (curpart == 0):
1468                 fatal("Trying to pop non-existent part")
1469         #print "End PART %s" % curpart.part
1470         # Warn if options are used without being set in this part
1471         for op in curpart.uses_options.keys():
1472                 if (not isset(op, curpart)):
1473                         notice("Option %s using default value %s" % (op, getformated(op, curpart.image)))
1474         oldpart = partstack.pop()
1475         dirstack.pop()
1476         #print "partstack.pop, TOS is now %s\n" % oldpart.info()
1477
1478 def dodir(path, file):
1479         """dodir is like part but there is no new part"""
1480         global dirstack
1481         # if the first char is '/', it is relative to treetop, 
1482         # else relative to curdir
1483         # os.path.join screws up if the name starts with '/', sigh.
1484         print "Configuring DIR %s" % os.path.join(path, file)
1485         if (path[0] == '/'):
1486                 fullpath = os.path.join(treetop, 'src')
1487                 path = re.sub('^/*', '', path)
1488         else:
1489                 fullpath = dirstack.tos()
1490         debug.info(debug.statement, "DODIR: path %s, fullpath %s" % (path, fullpath))
1491         dirstack.push(os.path.join(fullpath, path))
1492         doconfigfile(fullpath, path, file, 'cfgfile')
1493         dirstack.pop()
1494
1495 def lookup(name):
1496         global curimage
1497         return getoption(name, curimage)
1498
1499 def addrule(id):
1500         global curimage
1501         curimage.addmakerule(id)
1502         
1503 def adduserdefine(str):
1504         global curimage
1505         curimage.adduserdefine(str)
1506
1507 def addaction(id, str):
1508         global curimage
1509         curimage.addmakeaction(id, str)
1510
1511 def adddep(id, str):
1512         global curimage
1513         curimage.addmakedepend(id, str)
1514
1515 def setarch(my_arch):
1516         """arch is 'different' ... darn it."""
1517         global curimage
1518         print "SETTING ARCH %s\n" % my_arch
1519         curimage.setarch(my_arch)
1520         setdefault('ARCH', my_arch, 1)
1521         part('arch', my_arch, 'Config.lb', 0)
1522
1523 def doconfigfile(path, confdir, file, rule):
1524         rname = os.path.join(confdir, file)
1525         loc.push(rname)
1526         fullpath = os.path.join(path, rname)
1527         fp = safe_open(fullpath, 'r')
1528         if (not parse(rule, fp.read())):
1529                 fatal("Could not parse file")
1530         exitiferrors()
1531         loc.pop()
1532
1533 #=============================================================================
1534 #               MISC FUNCTIONS
1535 #=============================================================================
1536 def ternary(val, yes, no):
1537         debug.info(debug.statement, "ternary %s" % expr)
1538         debug.info(debug.statement, "expr %s a %d yes %d no %d"% (expr, a, yes, no))
1539         if (val == 0):
1540                 debug.info(debug.statement, "Ternary returns %d" % yes)
1541                 return yes
1542         else:
1543                 debug.info(debug.statement, "Ternary returns %d" % no)
1544                 return no
1545
1546 def tohex(name):
1547         """atoi is in the python library, but not strtol? Weird!"""
1548         return eval('int(%s)' % name)
1549
1550 def IsInt(str):
1551         """ Is the given string an integer?"""
1552         try:
1553                 num = long(str)
1554                 return 1
1555         except ValueError:
1556                 return 0
1557
1558 def dequote(str):
1559         a = re.sub("^\"", "", str)
1560         a = re.sub("\"$", "", a)
1561         # highly un-intuitive, need four \!
1562         a = re.sub("\\\\\"", "\"", a)
1563         return a
1564
1565 def flatten_name(str):
1566         a = re.sub("[/-]", "_", str)
1567         return a
1568
1569 def topify(path):
1570         """If the first part of <path> matches treetop, replace 
1571         that part with $(TOP)"""
1572         if path[0:len(treetop)] == treetop:
1573                 path = path[len(treetop):len(path)]
1574                 if (path[0:1] == "/"):
1575                         path = path[1:len(path)]
1576                 path = "$(TOP)/" + path
1577         return path
1578
1579 %%
1580 # to make if work without 2 passses, we use an old hack from SIMD, the 
1581 # context bit. If the bit is 1, then ops get done, otherwise
1582 # ops don't get done. From the top level, context is always
1583 # 1. In an if, context depends on eval of the if condition
1584
1585 parser Config:
1586     ignore:                     r'\s+'
1587     ignore:                     "#.*?\r?\n"
1588
1589     # less general tokens should come first, otherwise they get matched
1590     # by the re's
1591     token ACTION:               'action'
1592     token ADDACTION:            'addaction'
1593     token ALWAYS:               'always'
1594     token ARCH:                 'arch'
1595     token BUILDROM:             'buildrom'
1596     token COMMENT:              'comment'
1597     token CONFIG:               'config'
1598     token CPU:                  'cpu'
1599     token CPU_BUS:              'cpu_bus'
1600     token CHIP:                 'chip'
1601     token DEFAULT:              'default'
1602     token DEFINE:               'define'
1603     token DEPENDS:              'depends'
1604     token DEVICE:               'device'
1605     token DIR:                  'dir'
1606     token DRIVER:               'driver'
1607     token DRQ:                  'drq'
1608     token ELSE:                 'else'
1609     token END:                  'end'
1610     token EOF:                  '$'
1611     token EQ:                   '='
1612     token EXPORT:               'export'
1613     token FORMAT:               'format'
1614     token IF:                   'if'
1615     token INIT:                 'init'
1616     token INITOBJECT:           'initobject'
1617     token INITINCLUDE:          'initinclude'
1618     token IO:                   'io'
1619     token IRQ:                  'irq'
1620     token LDSCRIPT:             'ldscript'
1621     token LOADOPTIONS:          'loadoptions'
1622     token MAINBOARD:            'mainboard'
1623     token MAINBOARDINIT:        'mainboardinit'
1624     token MAKEDEFINE:           'makedefine'
1625     token MAKERULE:             'makerule'
1626     token MEM:                  'mem'
1627     token NEVER:                'never'
1628     token NONE:                 'none'
1629     token NORTHBRIDGE:          'northbridge'
1630     token OBJECT:               'object'
1631     token OPTION:               'option'
1632     token PAYLOAD:              'payload'
1633     token PMC:                  'pmc'
1634     token PRINT:                'print'
1635     token REGISTER:             'register'
1636     token ROMIMAGE:             'romimage'
1637     token SMMOBJECT:            'smmobject'
1638     token SOUTHBRIDGE:          'southbridge'
1639     token SUPERIO:              'superio'
1640     token TARGET:               'target'
1641     token USED:                 'used'
1642     token USES:                 'uses'
1643     token WRITE:                'write'
1644     token NUM:                  '[0-9]+'
1645     token HEX_NUM:              '[0-9a-fA-F]+'
1646     token HEX_PREFIX:           '0x'
1647     # Why is path separate? Because paths to resources have to at least
1648     # have a slash, we thinks
1649     token PATH:                 r'[-a-zA-Z0-9_.][-a-zA-Z0-9/_.]+[-a-zA-Z0-9_.]+'
1650     # Dir's on the other hand are abitrary
1651     # this may all be stupid.
1652     token RULE:                 r'[-a-zA-Z0-9_$()./]+[-a-zA-Z0-9_ $()./]+[-a-zA-Z0-9_$()./]+'
1653     token DIRPATH:              r'[-a-zA-Z0-9_$()./]+'
1654     token ID:                   r'[a-zA-Z_.]+[a-zA-Z0-9_.]*'
1655     token DELEXPR:              r'{([^}]+|\\.)*}'
1656     token STR:                  r'"([^\\"]+|\\.)*"'
1657     token RAWTEXT:              r'.*'
1658     token ON:                   'on'
1659     token OFF:                  'off'
1660     token PCI:                  'pci'
1661     token PNP:                  'pnp'
1662     token I2C:                  'i2c'
1663     token APIC:                 'apic'
1664     token APIC_CLUSTER:         'apic_cluster'
1665     token CPU:                  'cpu'
1666     token CPU_BUS:              'cpu_bus'
1667     token PCI_DOMAIN:           'pci_domain'
1668
1669
1670     rule expr:          logical                 {{ l = logical }}
1671                         ( "&&" logical          {{ l = l and logical }}
1672                         | "||"  logical         {{ l = l or logical }}
1673                         )*                      {{ return l }}
1674
1675     rule logical:       factor                  {{ n = factor }}
1676                         ( "[+]" factor          {{ n = n+factor }}
1677                         | "-"  factor           {{ n = n-factor }}
1678                         )*                      {{ return n }}
1679
1680     rule factor:        term                    {{ v = term }}
1681                         ( "[*]" term            {{ v = v*term }}
1682                         | "/"  term             {{ v = v/term }}
1683                         | "<<"  term            {{ v = v << term }}
1684                         | ">=" term             {{ v = (v < term)}}
1685                         )*                      {{ return v }}
1686
1687     # A term is a number, variable, or an expression surrounded by parentheses
1688     rule term:          NUM                     {{ return long(NUM, 10) }}
1689                 |       HEX_PREFIX HEX_NUM      {{ return long(HEX_NUM, 16) }}
1690                 |       ID                      {{ return lookup(ID) }}
1691                 |       unop                    {{ return unop }}
1692                 |       "\\(" expr "\\)"        {{ return expr }}
1693
1694     rule unop:          "!" expr                {{ return not(expr) }}
1695
1696     rule partend<<C>>:  (stmt<<C>>)* END        {{ if (C): partpop()}}
1697
1698     # This is needed because the legacy cpu command could not distinguish
1699     # between cpu vendors. It should just be PATH, but getting this change
1700     # into the source tree will be tricky... 
1701     # DO NOT USE ID AS IT MAY GO AWAY IN THE FUTURE
1702     rule partid:        ID                      {{ return ID }}
1703                 |       PATH                    {{ return PATH }}
1704
1705 #    rule parttype:     NORTHBRIDGE             {{ return 'northbridge' }} 
1706 #               |       SUPERIO                 {{ return 'superio' }}
1707 #               |       PMC                     {{ return 'pmc' }}
1708 #               |       SOUTHBRIDGE             {{ return 'southbridge' }}
1709 #               |       CPU                     {{ return 'cpu' }}
1710 #               |       CHIP                    {{ return '' }}
1711 #
1712     rule parttype:      CHIP                    {{ return '' }}
1713
1714     rule partdef<<C>>:                          {{ name = 0 }} 
1715                         parttype partid         
1716                         [ STR                   {{ name = dequote(STR) }}
1717                         ]                       {{ if (C): part(parttype, partid, 'Config.lb', name) }}
1718                         partend<<C>>            
1719
1720     rule arch<<C>>:     ARCH ID                 {{ if (C): setarch(ID) }}
1721                         partend<<C>>
1722     
1723     rule mainboardinit<<C>>:
1724                         MAINBOARDINIT DIRPATH   {{ if (C): addcrt0include(DIRPATH)}}
1725
1726     rule initinclude<<C>>: 
1727                         INITINCLUDE 
1728                         STR 
1729                         DIRPATH                 {{ if (C): addinitinclude(STR, DIRPATH)}}
1730
1731     rule initobject<<C>>:
1732                         INITOBJECT DIRPATH      {{ if (C): addinitobject(DIRPATH)}}
1733
1734     rule object<<C>>:   OBJECT DIRPATH          {{ if (C): addobject(DIRPATH)}}
1735
1736     rule driver<<C>>:   DRIVER DIRPATH          {{ if (C): adddriver(DIRPATH)}}
1737
1738     rule smmobject<<C>>:
1739                         SMMOBJECT DIRPATH       {{ if (C): addsmmobject(DIRPATH)}}
1740
1741
1742     rule dir<<C>>:      DIR DIRPATH             {{ if (C): dodir(DIRPATH, 'Config.lb') }}
1743
1744     rule default<<C>>:  DEFAULT ID EQ value     {{ if (C): setdefault(ID, value, 0) }}
1745
1746     rule ldscript<<C>>: LDSCRIPT DIRPATH        {{ if (C): addldscript(DIRPATH) }}
1747
1748     rule iif<<C>>:      IF ID                   {{ c = lookup(ID) }}
1749                         (stmt<<C and c>>)* 
1750                         [ ELSE (stmt<<C and not c>>)* ]
1751                         END
1752
1753     rule makerule<<C>>: MAKERULE RULE           {{ if (C): addrule(RULE) }}
1754                         ( DEPENDS STR           {{ if (C): adddep(RULE, STR) }}
1755                         | ACTION STR            {{ if (C): addaction(RULE, STR) }}
1756                         )*
1757                         END
1758
1759     rule makedefine<<C>>:
1760                         MAKEDEFINE RAWTEXT      {{ if (C): adduserdefine(RAWTEXT) }}
1761
1762     rule addaction<<C>>:
1763                         ADDACTION ID STR        {{ if (C): addaction(ID, STR) }}
1764
1765     rule init<<C>>:     INIT DIRPATH            {{ if (C): addinit(DIRPATH) }}
1766
1767     rule field:         STR                     {{ return STR }}
1768
1769     rule register<<C>>: REGISTER field '=' STR  {{ if (C): addregister(field, STR) }}
1770
1771     rule enable<<C>>:                           {{ val = 1 }}
1772                         ( ON                    {{ val = 1 }}
1773                         | OFF                   {{ val = 0 }}
1774                         )                       {{ if(C): partstack.tos().set_enabled(val) }}
1775
1776     rule resource<<C>>:                         {{ type = "" }}
1777                         (  IO                   {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IO" }}
1778                         |   MEM                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_MEM" }}
1779                         |   IRQ                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IRQ" }}
1780                         |   DRQ                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_DRQ" }}
1781                         )
1782                         term '='                {{ index = term }}
1783                         term                    {{ value = term }}
1784                                                 {{ if (C): partstack.tos().add_resource(type, index, value) }}
1785     
1786                              
1787     rule resources<<C>>:                        {{ if (C): partstack.tos().start_resources() }}
1788                         ( resource<<C>> )*
1789                                                 {{ if (C): partstack.tos().end_resources() }}
1790             
1791     
1792     rule pci<<C>>:      PCI                     {{ if (C): devicepart('pci') }}
1793
1794                         HEX_NUM                 {{ slot = int(HEX_NUM,16) }}
1795                         '.' HEX_NUM             {{ function = int(HEX_NUM, 16) }}
1796                                                 {{ if (C): partstack.tos().addpcipath(slot, function) }}
1797     rule pci_domain<<C>>:       
1798                         PCI_DOMAIN              {{ if (C): devicepart('pci_domain') }}
1799                         HEX_NUM                 {{ pci_domain = int(HEX_NUM, 16) }}
1800                                                 {{ if (C): partstack.tos().addpci_domainpath(pci_domain) }}
1801
1802     rule pnp<<C>>:      PNP                     {{ if (C): devicepart('pnp') }}
1803                         HEX_NUM                 {{ port = int(HEX_NUM,16) }}
1804                         '.' HEX_NUM             {{ device = int(HEX_NUM, 16) }}
1805                                                 {{ if (C): partstack.tos().addpnppath(port, device) }}
1806                                                 
1807     rule i2c<<C>>:      I2C                     {{ if (C): devicepart('i2c') }}
1808                         HEX_NUM                 {{ device = int(HEX_NUM, 16) }}
1809                                                 {{ if (C): partstack.tos().addi2cpath(device) }}
1810
1811     rule apic<<C>>:     APIC                    {{ if (C): devicepart('apic') }}
1812                         HEX_NUM                 {{ apic_id = int(HEX_NUM, 16) }}
1813                                                 {{ if (C): partstack.tos().addapicpath(apic_id) }}
1814
1815     rule apic_cluster<<C>>: APIC_CLUSTER        {{ if (C): devicepart('apic_cluster') }}
1816                         HEX_NUM                 {{ cluster = int(HEX_NUM, 16) }}
1817                                                 {{ if (C): partstack.tos().addapic_clusterpath(cluster) }}
1818
1819     rule cpu<<C>>:      CPU                     {{ if (C): devicepart('cpu') }}
1820                         HEX_NUM                 {{ id = int(HEX_NUM, 16) }}
1821                                                 {{ if (C): partstack.tos().addcpupath(id) }}
1822
1823     rule cpu_bus<<C>>:  CPU_BUS                 {{ if (C): devicepart('cpu_bus') }}
1824                         HEX_NUM                 {{ id = int(HEX_NUM, 16) }}
1825                                                 {{ if (C): partstack.tos().addcpu_buspath(id) }}
1826
1827     rule dev_path<<C>>:
1828                         pci<<C>>                {{ return pci }}
1829                 |       pci_domain<<C>>         {{ return pci_domain }}
1830                 |       pnp<<C>>                {{ return pnp }}
1831                 |       i2c<<C>>                {{ return i2c }}
1832                 |       apic<<C>>               {{ return apic }}
1833                 |       apic_cluster<<C>>       {{ return apic_cluster }}
1834                 |       cpu<<C>>                {{ return cpu }}
1835                 |       cpu_bus<<C>>            {{ return cpu_bus }}
1836                 
1837     rule prtval:        expr                    {{ return str(expr) }}
1838                 |       STR                     {{ return STR }}
1839
1840     rule prtlist:       prtval                  {{ el = "%(" + prtval }}
1841                         ( "," prtval            {{ el = el + "," + prtval }}
1842                         )*                      {{ return el + ")" }}   
1843
1844     rule prtstmt<<C>>:  PRINT STR               {{ val = STR }}
1845                         [ "," prtlist           {{ val = val + prtlist }}
1846                         ]                       {{ if (C): print eval(val) }}
1847
1848     rule config<<C>>:   CONFIG PATH             {{ if (C): addconfig(PATH) }}
1849
1850     rule device<<C>>:   DEVICE dev_path<<C>>
1851                         enable<<C>>                     
1852                         resources<<C>>
1853                         partend<<C>> 
1854
1855     rule stmt<<C>>:     arch<<C>>               {{ return arch}}
1856                 |       addaction<<C>>          {{ return addaction }}
1857                 |       config<<C>>             {{ return config}}
1858                 |       default<<C>>            {{ return default}}
1859                 |       dir<<C>>                {{ return dir}}
1860                 |       driver<<C>>             {{ return driver }}
1861                 |       iif<<C>>                {{ return iif }}
1862                 |       init<<C>>               {{ return init }}
1863                 |       initinclude<<C>>        {{ return initinclude }}
1864                 |       initobject<<C>>         {{ return initobject }}
1865                 |       ldscript<<C>>           {{ return ldscript}}
1866                 |       mainboardinit<<C>>      {{ return mainboardinit }}
1867                 |       makedefine<<C>>         {{ return makedefine }}
1868                 |       makerule<<C>>           {{ return makerule }}
1869                 |       object<<C>>             {{ return object }}
1870                 |       option<<C>>             {{ return option }}
1871                 |       partdef<<C>>            {{ return partdef }}
1872                 |       prtstmt<<C>>            {{ return prtstmt }}
1873                 |       register<<C>>           {{ return register }}
1874                 |       device<<C>>             {{ return device }}
1875                 |       smmobject<<C>>          {{ return smmobject }}
1876
1877     # ENTRY for parsing Config.lb file
1878     rule cfgfile:       (uses<<1>>)* 
1879                         (stmt<<1>>)*
1880                         EOF                     {{ return 1 }}
1881
1882     rule cfgfile:       (uses<<1>>)* 
1883                         (stmt<<1>>)*
1884                         EOF                     {{ return 1 }}
1885
1886     rule usesid<<C>>:   ID                      {{ if (C): usesoption(ID) }}
1887
1888     rule uses<<C>>:     USES (usesid<<C>>)+
1889
1890     rule mainboardvariables:    (uses<<1>>)*
1891                                 (default<<1>>)*
1892                                 (option<<1>>)*
1893                                 END             {{ return 1}}
1894
1895     rule value:         STR                     {{ return dequote(STR) }} 
1896                 |       expr                    {{ return expr }}
1897                 |       DELEXPR                 {{ return DELEXPR }}
1898
1899     rule option<<C>>:   OPTION ID EQ value      {{ if (C): setoption(ID, value, 0) }}
1900
1901     rule opif<<C>>:     IF ID                   {{ c = lookup(ID) }}
1902                         (opstmt<<C and c>>)* 
1903                         [ ELSE (opstmt<<C and not c>>)* ] 
1904                         END
1905
1906     rule opstmt<<C>>:   option<<C>>
1907                 |       opif<<C>>
1908                 |       prtstmt<<C>>
1909
1910     rule payload<<C>>:  PAYLOAD DIRPATH         {{ if (C): payload(DIRPATH) }}
1911
1912     rule mainboard:
1913                         MAINBOARD PATH          {{ mainboardsetup(PATH) }}
1914
1915     rule romif<<C>>:    IF ID                   {{ c = lookup(ID) }}
1916                         (romstmt<<C and c>>)* 
1917                         [ ELSE (romstmt<<C and not c>>)* ]
1918                         END
1919
1920     rule romstmt<<C>>:  romif<<C>>
1921                 |       option<<C>>
1922                 |       payload<<C>>
1923
1924     rule romimage:      ROMIMAGE STR            {{ startromimage(dequote(STR)) }}
1925                         (romstmt<<1>>)*
1926                         END                     {{ endromimage() }}
1927
1928     rule roms:          STR                     {{ s = '[' + STR }}
1929                         ( STR                   {{ s = s + "," + STR }}
1930                         )*                      {{ return eval(s + ']') }}
1931
1932     rule buildrom:      BUILDROM DIRPATH expr roms      {{ addbuildrom(DIRPATH, expr, roms) }}
1933
1934     rule romstmts:      romimage 
1935                 |       buildrom
1936                 |       opstmt<<1>>
1937
1938     # ENTRY for parsing root part
1939     rule board:         {{ loadoptions("config", "Options.lb", "options") }}
1940                         TARGET DIRPATH          {{ target(DIRPATH) }}
1941                         mainboard
1942                         (romstmts)*             
1943                         EOF                     {{ return 1 }}
1944
1945     # ENTRY for parsing a delayed value
1946     rule delexpr:       "{" expr "}" EOF        {{ return expr }}
1947
1948     rule wrstr<<ID>>:   STR                     {{ setwrite(ID, dequote(STR)) }}
1949
1950     rule defstmts<<ID>>:                        {{ d = 0 }}
1951                         ( DEFAULT
1952                           ( value               {{ setdefault(ID, value, 1) }}
1953                           | NONE                {{ setnodefault(ID) }}
1954                           )                     {{ d = d | 1 }}
1955                         | FORMAT STR            {{ setformat(ID, dequote(STR)) }}
1956                         | EXPORT 
1957                           ( ALWAYS              {{ setexported(ID) }}
1958                           | USED                {{ setexportable(ID) }}
1959                           | NEVER               {{ setnoexport(ID) }}
1960                           )                     {{ d = d | 2 }}
1961                         | COMMENT STR           {{ setcomment(ID, dequote(STR)); d = d | 4 }}
1962                         | WRITE (wrstr<<ID>>)+
1963                         )+                      {{ return d }}
1964                 
1965     rule define:        DEFINE ID               {{ newoption(ID) }}
1966                         defstmts<<ID>> END      {{ validdef(ID, defstmts) }}
1967
1968     # ENTRY for parsing Options.lb file
1969     rule options:       (define)* EOF           {{ return 1 }}
1970 %%
1971
1972 #=============================================================================
1973 #               FILE OUTPUT 
1974 #=============================================================================
1975 def writemakefileheader(file, fname):
1976         file.write("# File: %s is autogenerated\n" % fname)
1977
1978 def writemakefilefooter(file, fname):
1979         file.write("\n\n%s: %s %s\n"
1980                 % (os.path.basename(fname), os.path.abspath(sys.argv[0]), top_config_file))
1981         file.write("\t(cd %s ; export PYTHONPATH=%s/util/newconfig ; python %s %s %s)\n\n"
1982                 % (os.getcwd(), treetop, sys.argv[0], sys.argv[1], sys.argv[2]))
1983
1984 def writemakefilesettings(path):
1985         """ Write Makefile.settings to seperate the settings
1986         from the actual makefile creation."""
1987
1988         global treetop, target_dir
1989
1990         filename = os.path.join(path, "Makefile.settings")
1991         print "Creating", filename
1992         file = safe_open(filename, 'w+')
1993         writemakefileheader(file, filename)
1994         file.write("TOP:=%s\n" % (treetop))
1995         file.write("TARGET_DIR:=%s\n" % target_dir)
1996         writemakefilefooter(file, filename)
1997         file.close()
1998
1999 def writeimagesettings(image):
2000         """Write Makefile.settings to seperate the settings
2001         from the actual makefile creation."""
2002
2003         global treetop
2004         global global_options_by_order
2005
2006         filename = os.path.join(image.gettargetdir(), "Makefile.settings")
2007         print "Creating", filename
2008         file = safe_open(filename, 'w+')
2009         writemakefileheader(file, filename)
2010         file.write("TOP:=%s\n" % (treetop))
2011         file.write("TARGET_DIR:=%s\n" % (image.gettargetdir()))
2012         file.write("\n")
2013         exported = []
2014         for o in global_exported_options:
2015                 exported.append(o)
2016         for o in image.exported_options:
2017                 if (not o in exported):
2018                         exported.append(o)
2019         for o in exported:
2020                 file.write("export %s:=" % o.name)
2021                 if (hasvalue(o.name, image)):
2022                         file.write("%s" % getformated(o.name, image))
2023                 file.write("\n")
2024         file.write("\n")
2025         file.write("export VARIABLES :=\n")
2026         for o in exported:
2027                 file.write("export VARIABLES += %s\n" % o.name)
2028         file.write("\n")
2029         writemakefilefooter(file,filename)
2030         file.close()
2031
2032 # write the romimage makefile
2033 # let's try the Makefile
2034 # first, dump all the -D stuff
2035
2036 def writeimagemakefile(image):
2037         makefilepath = os.path.join(image.gettargetdir(), "Makefile")
2038         print "Creating", makefilepath
2039         file = safe_open(makefilepath, 'w+')
2040         writemakefileheader(file, makefilepath)
2041
2042         # main rule
2043         file.write("\nall: coreboot.rom\n\n")
2044         file.write(".PHONY: all\n\n")
2045         #file.write("include cpuflags\n")
2046         # Putting "include cpuflags" in the Makefile has the problem that the
2047         # cpuflags file would be generated _after_ we want to include it.
2048         # Instead, let make do the work of computing CPUFLAGS:
2049         file.write("# Get the value of TOP, VARIABLES, and several other variables.\n")
2050         file.write("include Makefile.settings\n\n")
2051         file.write("# Function to create an item like -Di586 or -DCONFIG_MAX_CPUS='1' or -Ui686\n")
2052         file.write("D_item = $(if $(subst undefined,,$(origin $1)),-D$1$(if $($1),='$($1)',),-U$1)\n\n")
2053         file.write("# Compute the value of CPUFLAGS here during make's first pass.\n")
2054         file.write("CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))\n\n")
2055
2056         for i in image.getuserdefines():
2057                 file.write("%s\n" %i)
2058         file.write("\n")
2059
2060         # print out all the object dependencies
2061         file.write("\n# object dependencies (objectrules:)\n")
2062         file.write("INIT-OBJECTS :=\n")
2063         file.write("OBJECTS :=\n")
2064         file.write("DRIVER :=\n")
2065         file.write("\nSOURCES :=\n")
2066         for irule, init in image.getinitobjectrules().items():
2067                 i_name = init[0]
2068                 i_source = init[1]
2069                 file.write("INIT-OBJECTS += %s\n" % (i_name))
2070                 file.write("SOURCES += %s\n" % (i_source))
2071
2072         for objrule, obj in image.getobjectrules().items():
2073                 obj_name = obj[0]
2074                 obj_source = obj[1]
2075                 file.write("OBJECTS += %s\n" % (obj_name))
2076                 file.write("SOURCES += %s\n" % (obj_source))
2077
2078         for srule, smm in image.getsmmobjectrules().items():
2079                 s_name = smm[0]
2080                 s_source = smm[1]
2081                 file.write("SMM-OBJECTS += %s\n" % (s_name))
2082                 file.write("SOURCES += %s\n" % (s_source))
2083
2084
2085         # for chip_target.c
2086         file.write("OBJECTS += static.o\n")
2087         file.write("SOURCES += static.c\n")
2088
2089         for driverrule, driver in image.getdriverrules().items():
2090                 obj_name = driver[0]
2091                 obj_source = driver[1]
2092                 file.write("DRIVER += %s\n" % (obj_name))
2093                 file.write("SOURCES += %s\n" % (obj_source))
2094
2095         # Print out all ldscript.ld dependencies.
2096         file.write("\n# ldscript.ld dependencies:\n")
2097         file.write("LDSUBSCRIPTS-1 := \n" )
2098         for script in image.getldscripts():
2099                 file.write("LDSUBSCRIPTS-1 += %s\n" % topify(script))
2100
2101         # Print out the dependencies for crt0_includes.h
2102         file.write("\n# Dependencies for crt0_includes.h\n")
2103         file.write("CRT0_INCLUDES:=\n")
2104         for inc in image.getinitincludes():
2105                 if (local_path.match(inc)):
2106                         file.write("CRT0_INCLUDES += %s\n" % inc)
2107                 else:
2108                         file.write("CRT0_INCLUDES += $(TOP)/src/%s\n" % inc)
2109
2110         # Print out the user defines.
2111         file.write("\n# userdefines:\n")
2112                 
2113         # Print out the base rules.
2114         # Need to have a rule that counts on 'all'.
2115         file.write("\n# mainrulelist:")
2116
2117         # Print out any user rules.
2118         file.write("\n# From makerule or docipl commands:\n")
2119
2120         file.write("\n# initobjectrules:\n")
2121         for irule, init in image.getinitobjectrules().items():
2122                 source = topify(init[1])
2123                 type = init[2]
2124                 if (type  == 'S'):
2125                         # for .S, .o depends on .s
2126                         file.write("%s: %s.s\n" % (init[0], init[3]))
2127                         file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n")
2128                         # and .s depends on .S
2129                         file.write("%s.s: %s\n" % (init[3], source))
2130                         # Note: next 2 lines are ONE output line!
2131                         file.write("\t$(CPP) $(CPPFLAGS) $< ")
2132                         file.write(">$@.new && mv $@.new $@\n")
2133                 else:
2134                         file.write("%s: %s\n" % (init[0], source))
2135                         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2136
2137         file.write("\n# objectrules:\n")
2138         for objrule, obj in image.getobjectrules().items():
2139                 source = topify(obj[1])
2140                 type = obj[2]
2141                 if (type  == 'S'):
2142                         # for .S, .o depends on .s
2143                         file.write("%s: %s.s\n" % (obj[0], obj[3]))
2144                         file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n")
2145                         # and .s depends on .S
2146                         file.write("%s.s: %s\n" % (obj[3], source))
2147                         # Note: next 2 lines are ONE output line!
2148                         file.write("\t$(CPP) $(CPPFLAGS) $< ")
2149                         file.write(">$@.new && mv $@.new $@\n")
2150                 else:
2151                         file.write("%s: %s\n" % (obj[0], source))
2152                         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2153                 #file.write("%s\n" % objrule[2])
2154
2155         for driverrule, driver in image.getdriverrules().items():
2156                 source = topify(driver[1])
2157                 file.write("%s: %s\n" % (driver[0], source))
2158                 file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2159                 #file.write("%s\n" % objrule[2])
2160
2161         file.write("\n# smmobjectrules:\n")
2162         for irule, smm in image.getsmmobjectrules().items():
2163                 source = topify(smm[1])
2164                 type = smm[2]
2165                 if (type  == 'S'):
2166                         # for .S, .o depends on .s
2167                         file.write("%s: %s.s\n" % (smm[0], smm[3]))
2168                         file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n")
2169                         # and .s depends on .S
2170                         file.write("%s.s: %s\n" % (smm[3], source))
2171                         # Note: next 2 lines are ONE output line!
2172                         file.write("\t$(CPP) $(CPPFLAGS) $< ")
2173                         file.write(">$@.new && mv $@.new $@\n")
2174                 else:
2175                         file.write("%s: %s\n" % (smm[0], source))
2176                         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2177
2178         # special rule for chip_target.c
2179         file.write("static.o: static.c\n")
2180         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2181
2182         # Print out the rules that will make cause the files
2183         # generated by NLBConfig.py to be remade if any dependencies change.
2184
2185         file.write("\n# Remember the automatically generated files\n")
2186         file.write("GENERATED:=\n")
2187         for genfile in ['Makefile',
2188                         'nsuperio.c',
2189                         'static.c',
2190                         'corebootDoc.config' ]:
2191                 file.write("GENERATED += %s\n" % genfile)
2192         file.write("GENERATED += %s\n" % image.getincludefilename())
2193
2194         keys = global_options_by_order
2195         keys.sort()
2196         file.write("\necho:\n")
2197         for key in keys:
2198                  file.write("\t@echo %s='$(%s)'\n"% (key,key))
2199
2200         for i, m in image.getmakerules().items():
2201                 file.write("%s: " %i)
2202                 for i in m.dependency:
2203                         file.write("%s " % i)
2204                 file.write("\n")
2205                 for i in m.actions:
2206                         file.write("\t%s\n" % i)
2207         writemakefilefooter(file, makefilepath)
2208         file.close()
2209
2210 #
2211 def writemakefile(path):
2212         makefilepath = os.path.join(path, "Makefile")
2213         print "Creating", makefilepath
2214         file = safe_open(makefilepath, 'w+')
2215         writemakefileheader(file, makefilepath)
2216
2217         # main rule
2218         file.write("\nall:")
2219         for i in buildroms:
2220                 file.write(" %s" % i.name)
2221         file.write("\n\n")      
2222         file.write("include Makefile.settings\n\n")
2223         for i, o in romimages.items():
2224                 file.write("%s/coreboot.rom:\n" % o.getname())
2225                 file.write("\tif (cd %s; \\\n" % o.getname())
2226                 file.write("\t\t$(MAKE) coreboot.rom)\\\n")
2227                 file.write("\tthen true; else exit 1; fi;\n\n")
2228         file.write("clean: ")
2229         for i in romimages.keys():
2230                 file.write(" %s-clean" % i)
2231         file.write(" base-clean")
2232         file.write("\n\n")
2233         for i, o in romimages.items():
2234                 file.write("%s-clean:\n" % o.getname())
2235                 file.write("\t(cd %s; $(MAKE) clean)\n\n" % o.getname())
2236         file.write("base-clean:\n")
2237         file.write("\trm -f romcc*\n\n")
2238
2239         for i in buildroms:
2240                 file.write("%s:" % i.name)
2241                 for j in i.roms:
2242                         file.write(" %s/coreboot.rom " % j)
2243                 file.write("\n")
2244                 file.write("\t cat ")
2245                 for j in i.roms:
2246                         file.write(" %s/coreboot.rom " % j)
2247                 file.write("> %s\n\n" %i.name)
2248
2249
2250         file.write(".PHONY: all clean")
2251         for i in romimages.keys():
2252                 file.write(" %s-clean" % i)
2253         for i, o in romimages.items():
2254                 file.write(" %s/coreboot.rom" % o.getname())
2255         file.write("\n\n")
2256
2257         writemakefilefooter(file, makefilepath)
2258         file.close()
2259
2260 def writeinitincludes(image):
2261         global include_pattern
2262         filepath = os.path.join(image.gettargetdir(), image.getincludefilename())
2263         print "Creating", filepath
2264         outfile = safe_open(filepath, 'w+')
2265         if (image.newformat()):
2266                 infile = safe_open(image.getinitfile(), 'r')
2267
2268                 line = infile.readline()
2269                 while (line):
2270                         p = include_pattern.match(line)
2271                         if (p):
2272                                 for i in image.getinitincludes():
2273                                         inc = image.getinitinclude(i)
2274                                         if (inc.getstring() == p.group(1)):
2275                                                 outfile.write("#include \"%s\"\n" % inc.getpath())
2276                         else:
2277                                 outfile.write(line)
2278                         line = infile.readline()
2279
2280                 infile.close()
2281         else:
2282                 for i in image.getinitincludes():
2283                         outfile.write("#include <%s>\n" % i)
2284         outfile.close()
2285
2286 def writeldoptions(image):
2287         """Write ldoptions file."""
2288         filename = os.path.join(image.gettargetdir(), "ldoptions")
2289         print "Creating", filename
2290         file = safe_open(filename, 'w+')
2291         for o in global_exported_options:
2292                 if (hasvalue(o.name, image) and IsInt(getoption(o.name, image))):
2293                         file.write("%s = %s;\n" % (o.name, getformated(o.name, image)))
2294         for o in image.exported_options:
2295                 if (not o in global_exported_options and hasvalue(o.name, image) and IsInt(getoption(o.name, image))):
2296                         file.write("%s = %s;\n" % (o.name, getformated(o.name, image)))
2297         file.close()
2298
2299 def dumptree(part, lvl):
2300         debug.info(debug.dumptree, "DUMPTREE ME is")
2301         part.dumpme(lvl)
2302         # dump the siblings -- actually are there any? not sure
2303         # siblings are:
2304         debug.info(debug.dumptree, "DUMPTREE SIBLINGS are")
2305         kid = part.next_sibling
2306         while (kid):
2307                 kid.dumpme(lvl)
2308                 kid = kid.next_sibling
2309         # dump the kids
2310         debug.info(debug.dumptree, "DUMPTREE KIDS are")
2311         #for kid in part.children:
2312         if (part.children):
2313                 dumptree(part.children, lvl+1)
2314         kid = part.next_sibling
2315         while (kid):
2316                 if (kid.children):
2317                         dumptree(kid.children, lvl + 1)
2318                 kid = kid.next_sibling
2319         debug.info(debug.dumptree, "DONE DUMPTREE")
2320
2321 def writecode(image):
2322         filename = os.path.join(img_dir, "static.c")
2323         print "Creating", filename
2324         file = safe_open(filename, 'w+')
2325         file.write("#include <device/device.h>\n")
2326         file.write("#include <device/pci.h>\n")
2327         for path in image.getconfigincludes().values():
2328                 file.write("#include \"%s\"\n" % path)
2329         file.write("\n/* pass 0 */\n")
2330         gencode(image.getroot(), file, 0)
2331         file.write("\n/* pass 1 */\n")
2332         gencode(image.getroot(), file, 1)
2333         file.close()
2334
2335 def gencode(part, file, pass_num):
2336         debug.info(debug.gencode, "GENCODE ME is")
2337         part.gencode(file, pass_num)
2338         # dump the siblings -- actually are there any? not sure
2339         debug.info(debug.gencode, "GENCODE SIBLINGS are")
2340         kid = part.next_sibling
2341         while (kid):
2342                 kid.gencode(file, pass_num)
2343                 kid = kid.next_sibling
2344         # now dump the children 
2345         debug.info(debug.gencode, "GENCODE KIDS are")
2346         if (part.children):
2347                 gencode(part.children, file, pass_num)
2348         kid = part.next_sibling
2349         while (kid):
2350                 if (kid.children):
2351                         gencode(kid.children, file, pass_num)
2352                 kid = kid.next_sibling
2353         debug.info(debug.gencode, "DONE GENCODE")
2354
2355 def writegraph(image):
2356         filename = os.path.join(img_dir, "static.dot")
2357         print "Creating", filename
2358         file = safe_open(filename, 'w+')
2359         file.write("digraph devicetree {\n")
2360         file.write("    rankdir=LR\n")
2361         genranks(image.getroot(), file, 0)
2362         gennodes(image.getroot(), file)
2363         gengraph(image.getroot(), file)
2364         file.write("}\n")
2365         file.close()
2366
2367 def genranks(part, file, level):
2368         #file.write("   # Level %d\n" % level )
2369         file.write("    { rank = same; \"dev_%s_%d\"" % (part.type_name,part.instance ))
2370         sib = part.next_sibling
2371         while (sib):
2372                 file.write("; \"dev_%s_%d\"" % (sib.type_name, sib.instance))
2373                 sib = sib.next_sibling
2374         file.write("}\n" )
2375         # now dump the children 
2376         if (part.children):
2377                 genranks(part.children, file, level + 1)
2378
2379         kid = part.next_sibling
2380         while (kid):
2381                 if (kid.children):
2382                         genranks(kid.children, file, level + 1)
2383                 kid = kid.next_sibling
2384
2385
2386 def gennodes(part, file):
2387         file.write("    dev_%s_%d[shape=record, label=\"%s\"];\n" % (part.type_name,part.instance,part.graph_name() ))
2388         sib = part.next_sibling
2389         while (sib):
2390                 file.write("    dev_%s_%d[shape=record, label=\"%s\"];\n" % (sib.type_name,sib.instance,sib.graph_name() ))
2391                 sib = sib.next_sibling
2392         # now dump the children
2393         if (part.children):
2394                 gennodes(part.children, file)
2395
2396         kid = part.next_sibling
2397         while (kid):
2398                 if (kid.children):
2399                         gennodes(kid.children, file)
2400                 kid = kid.next_sibling
2401
2402
2403 def gengraph(part, file):
2404         if (part.parent != part):
2405                 file.write("    dev_%s_%d -> dev_%s_%d;\n" % \
2406                                 (part.parent.type_name, part.parent.instance, \
2407                                  part.type_name, part.instance ))
2408         sib = part.next_sibling
2409         while (sib):
2410                 file.write("    dev_%s_%d -> dev_%s_%d;\n" % \
2411                                 (sib.parent.type_name, sib.parent.instance, \
2412                                  sib.type_name, sib.instance ))
2413                 sib = sib.next_sibling
2414
2415         kid = part.next_sibling
2416         while (kid):
2417                 if (kid.children):
2418                         gengraph(kid.children, file)
2419                 kid = kid.next_sibling
2420
2421         if (part.children):
2422                 gengraph(part.children, file)
2423
2424 def verifyparse():
2425         """Add any run-time checks to verify that parsing the configuration
2426         was successful"""
2427
2428         for image in romimages.values():
2429                 print("Verifying ROMIMAGE %s" % image.name)
2430                 if (image.newformat() and image.getinitfile() == ''):
2431                         fatal("An init file must be specified")
2432                 for op in image.exported_options:
2433                         if (getoptionvalue(op.name, op, image) == 0 and getoptionvalue(op.name, op, 0) == 0):
2434                                 warning("Exported option %s has no value (check Options.lb)" % op.name);
2435         print("Verifing global options")
2436         for op in global_exported_options:
2437                 if (getoptionvalue(op.name, op, 0) == 0):
2438                         notice("Exported option %s has no value (check Options.lb)" % op.name);
2439                         
2440 #=============================================================================
2441 #               MAIN PROGRAM
2442 #=============================================================================
2443 if __name__=='__main__':
2444         from sys import argv
2445         if (len(argv) < 3):
2446                 fatal("Args: <file> <path to coreboot>")
2447
2448         top_config_file = os.path.abspath(sys.argv[1])
2449
2450         treetop = os.path.abspath(sys.argv[2])
2451
2452         # Now read in the customizing script...
2453         loc.push(argv[1])
2454         fp = safe_open(argv[1], 'r')
2455         if (not parse('board', fp.read())):
2456                 fatal("Could not parse file")
2457         loc.pop()
2458
2459         verifyparse()
2460
2461         # no longer need to check if an options has been used
2462         alloptions = 1
2463
2464         for image_name, image in romimages.items():
2465                 if (debug.level(debug.dumptree)):
2466                         debug.info(debug.dumptree, "DEVICE TREE:")
2467                         dumptree(image.getroot(), 0)
2468
2469                 img_dir = image.gettargetdir()
2470                 if not os.path.isdir(img_dir):
2471                         print "Creating directory %s" % img_dir
2472                         os.makedirs(img_dir)
2473
2474                 for objrule, obj in image.getobjectrules().items():
2475                         sub_dir = img_dir + '/' + os.path.dirname(obj[0])
2476                         if not os.path.isdir(sub_dir):
2477                                 print "Creating sub directory %s" % sub_dir
2478                                 os.makedirs(sub_dir)
2479
2480                 for driverrule, driver in image.getdriverrules().items():
2481                         sub_dir = img_dir + '/' + os.path.dirname(driver[0])
2482                         if not os.path.isdir(sub_dir):
2483                                 print "Creating sub directory %s" % sub_dir
2484                                 os.makedirs(sub_dir)
2485
2486                 for srule, smm in image.getsmmobjectrules().items():
2487                         sub_dir = img_dir + '/' + os.path.dirname(smm[0])
2488                         if not os.path.isdir(sub_dir):
2489                                 print "Creating sub directory %s" % sub_dir
2490                                 os.makedirs(sub_dir)
2491
2492                 for irule, init in image.getinitobjectrules().items():
2493                         sub_dir = img_dir + '/' + os.path.dirname(init[0])
2494                         if not os.path.isdir(sub_dir):
2495                                 print "Creating sub directory %s" % sub_dir
2496                                 os.makedirs(sub_dir)
2497
2498                 if (debug.level(debug.dump)):
2499                         for i in image.getinitincludes():
2500                                 debug.info(debug.dump, "crt0include file %s" % i)
2501                         for i in image.getdriverrules().keys():
2502                                 debug.info(debug.dump, "driver file %s" % i)
2503                         for i in image.getldscripts():
2504                                 debug.info(debug.dump, "ldscript file %s" % i)
2505                         for i, m in image.getmakerules().items():
2506                                 debug.info(debug.dump, " makerule %s dep %s act %s" % (i, m.dependency, m.actions))
2507
2508                 writecode(image)
2509                 writeimagesettings(image)
2510                 writeinitincludes(image)
2511                 writeimagemakefile(image)
2512                 writeldoptions(image)
2513                 writegraph(image)
2514
2515         writemakefilesettings(target_dir)
2516         writemakefile(target_dir)
2517
2518         sys.exit(0)