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