This patch allows you to add lines of the form
[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 lookup(name):
1518         global curimage
1519         return getoption(name, curimage)
1520
1521 def addrule(id):
1522         global curimage
1523         curimage.addmakerule(id)
1524         
1525 def adduserdefine(str):
1526         global curimage
1527         curimage.adduserdefine(str)
1528
1529 def addaction(id, str):
1530         global curimage
1531         curimage.addmakeaction(id, str)
1532
1533 def adddep(id, str):
1534         global curimage
1535         curimage.addmakedepend(id, str)
1536
1537 def setarch(my_arch):
1538         """arch is 'different' ... darn it."""
1539         global curimage
1540         print "SETTING ARCH %s\n" % my_arch
1541         curimage.setarch(my_arch)
1542         setdefault('ARCH', my_arch, 1)
1543         part('arch', my_arch, 'Config.lb', 0)
1544
1545 def doconfigfile(path, confdir, file, rule):
1546         rname = os.path.join(confdir, file)
1547         loc.push(rname)
1548         fullpath = os.path.join(path, rname)
1549         fp = safe_open(fullpath, 'r')
1550         if (not parse(rule, fp.read())):
1551                 fatal("Could not parse file")
1552         exitiferrors()
1553         loc.pop()
1554
1555 #=============================================================================
1556 #               MISC FUNCTIONS
1557 #=============================================================================
1558 def ternary(val, yes, no):
1559         debug.info(debug.statement, "ternary %s" % expr)
1560         debug.info(debug.statement, "expr %s a %d yes %d no %d"% (expr, a, yes, no))
1561         if (val == 0):
1562                 debug.info(debug.statement, "Ternary returns %d" % yes)
1563                 return yes
1564         else:
1565                 debug.info(debug.statement, "Ternary returns %d" % no)
1566                 return no
1567
1568 def tohex(name):
1569         """atoi is in the python library, but not strtol? Weird!"""
1570         return eval('int(%s)' % name)
1571
1572 def IsInt(str):
1573         """ Is the given string an integer?"""
1574         try:
1575                 num = long(str)
1576                 return 1
1577         except ValueError:
1578                 return 0
1579
1580 def dequote(str):
1581         a = re.sub("^\"", "", str)
1582         a = re.sub("\"$", "", a)
1583         # highly un-intuitive, need four \!
1584         a = re.sub("\\\\\"", "\"", a)
1585         return a
1586
1587 def flatten_name(str):
1588         a = re.sub("[/-]", "_", str)
1589         return a
1590
1591 def topify(path):
1592         """If the first part of <path> matches treetop, replace 
1593         that part with $(TOP)"""
1594         if path[0:len(treetop)] == treetop:
1595                 path = path[len(treetop):len(path)]
1596                 if (path[0:1] == "/"):
1597                         path = path[1:len(path)]
1598                 path = "$(TOP)/" + path
1599         return path
1600
1601 %%
1602 # to make if work without 2 passses, we use an old hack from SIMD, the 
1603 # context bit. If the bit is 1, then ops get done, otherwise
1604 # ops don't get done. From the top level, context is always
1605 # 1. In an if, context depends on eval of the if condition
1606
1607 parser Config:
1608     ignore:                     r'\s+'
1609     ignore:                     "#.*?\r?\n"
1610
1611     # less general tokens should come first, otherwise they get matched
1612     # by the re's
1613     token ACTION:               'action'
1614     token ADDACTION:            'addaction'
1615     token ALWAYS:               'always'
1616     token ARCH:                 'arch'
1617     token BUILDROM:             'buildrom'
1618     token COMMENT:              'comment'
1619     token CONFIG:               'config'
1620     token CPU:                  'cpu'
1621     token CPU_BUS:              'cpu_bus'
1622     token CHIP:                 'chip'
1623     token DEFAULT:              'default'
1624     token DEFINE:               'define'
1625     token DEPENDS:              'depends'
1626     token DEVICE:               'device'
1627     token DEVICE_ID:            'device_id'
1628     token DIR:                  'dir'
1629     token DRIVER:               'driver'
1630     token DRQ:                  'drq'
1631     token ELSE:                 'else'
1632     token END:                  'end'
1633     token EOF:                  '$'
1634     token EQ:                   '='
1635     token EXPORT:               'export'
1636     token FORMAT:               'format'
1637     token IF:                   'if'
1638     token INIT:                 'init'
1639     token INITOBJECT:           'initobject'
1640     token INITINCLUDE:          'initinclude'
1641     token IO:                   'io'
1642     token IRQ:                  'irq'
1643     token LDSCRIPT:             'ldscript'
1644     token LOADOPTIONS:          'loadoptions'
1645     token MAINBOARD:            'mainboard'
1646     token MAINBOARDINIT:        'mainboardinit'
1647     token MAKEDEFINE:           'makedefine'
1648     token MAKERULE:             'makerule'
1649     token MEM:                  'mem'
1650     token NEVER:                'never'
1651     token NONE:                 'none'
1652     token NORTHBRIDGE:          'northbridge'
1653     token OBJECT:               'object'
1654     token OPTION:               'option'
1655     token PAYLOAD:              'payload'
1656     token PCI_ROM:              'pci_rom'
1657     token PMC:                  'pmc'
1658     token PRINT:                'print'
1659     token REGISTER:             'register'
1660     token ROMIMAGE:             'romimage'
1661     token SMMOBJECT:            'smmobject'
1662     token SOUTHBRIDGE:          'southbridge'
1663     token SUPERIO:              'superio'
1664     token TARGET:               'target'
1665     token USED:                 'used'
1666     token USES:                 'uses'
1667     token VENDOR_ID:            'vendor_id'
1668     token WRITE:                'write'
1669     token NUM:                  '[0-9]+'
1670     token HEX_NUM:              '[0-9a-fA-F]+'
1671     token HEX_PREFIX:           '0x'
1672     # Why is path separate? Because paths to resources have to at least
1673     # have a slash, we thinks
1674     token PATH:                 r'[-a-zA-Z0-9_.][-a-zA-Z0-9/_.]+[-a-zA-Z0-9_.]+'
1675     # Dir's on the other hand are abitrary
1676     # this may all be stupid.
1677     token RULE:                 r'[-a-zA-Z0-9_$()./]+[-a-zA-Z0-9_ $()./]+[-a-zA-Z0-9_$()./]+'
1678     token DIRPATH:              r'[-a-zA-Z0-9_$()./]+'
1679     token ID:                   r'[a-zA-Z_.]+[a-zA-Z0-9_.]*'
1680     token DELEXPR:              r'{([^}]+|\\.)*}'
1681     token STR:                  r'"([^\\"]+|\\.)*"'
1682     token RAWTEXT:              r'.*'
1683     token ON:                   'on'
1684     token OFF:                  'off'
1685     token PCI:                  'pci'
1686     token PNP:                  'pnp'
1687     token I2C:                  'i2c'
1688     token APIC:                 'apic'
1689     token APIC_CLUSTER:         'apic_cluster'
1690     token CPU:                  'cpu'
1691     token CPU_BUS:              'cpu_bus'
1692     token PCI_DOMAIN:           'pci_domain'
1693
1694
1695     rule expr:          logical                 {{ l = logical }}
1696                         ( "&&" logical          {{ l = l and logical }}
1697                         | "||"  logical         {{ l = l or logical }}
1698                         )*                      {{ return l }}
1699
1700     rule logical:       factor                  {{ n = factor }}
1701                         ( "[+]" factor          {{ n = n+factor }}
1702                         | "-"  factor           {{ n = n-factor }}
1703                         )*                      {{ return n }}
1704
1705     rule factor:        term                    {{ v = term }}
1706                         ( "[*]" term            {{ v = v*term }}
1707                         | "/"  term             {{ v = v/term }}
1708                         | "<<"  term            {{ v = v << term }}
1709                         | ">=" term             {{ v = (v < term)}}
1710                         )*                      {{ return v }}
1711
1712     # A term is a number, variable, or an expression surrounded by parentheses
1713     rule term:          NUM                     {{ return long(NUM, 10) }}
1714                 |       HEX_PREFIX HEX_NUM      {{ return long(HEX_NUM, 16) }}
1715                 |       ID                      {{ return lookup(ID) }}
1716                 |       unop                    {{ return unop }}
1717                 |       "\\(" expr "\\)"        {{ return expr }}
1718
1719     rule unop:          "!" expr                {{ return not(expr) }}
1720
1721     rule partend<<C>>:  (stmt<<C>>)* END        {{ if (C): partpop()}}
1722
1723     # This is needed because the legacy cpu command could not distinguish
1724     # between cpu vendors. It should just be PATH, but getting this change
1725     # into the source tree will be tricky... 
1726     # DO NOT USE ID AS IT MAY GO AWAY IN THE FUTURE
1727     rule partid:        ID                      {{ return ID }}
1728                 |       PATH                    {{ return PATH }}
1729
1730 #    rule parttype:     NORTHBRIDGE             {{ return 'northbridge' }} 
1731 #               |       SUPERIO                 {{ return 'superio' }}
1732 #               |       PMC                     {{ return 'pmc' }}
1733 #               |       SOUTHBRIDGE             {{ return 'southbridge' }}
1734 #               |       CPU                     {{ return 'cpu' }}
1735 #               |       CHIP                    {{ return '' }}
1736 #
1737     rule parttype:      CHIP                    {{ return '' }}
1738
1739     rule partdef<<C>>:                          {{ name = 0 }} 
1740                         parttype partid         
1741                         [ STR                   {{ name = dequote(STR) }}
1742                         ]                       {{ if (C): part(parttype, partid, 'Config.lb', name) }}
1743                         partend<<C>>            
1744
1745     rule arch<<C>>:     ARCH ID                 {{ if (C): setarch(ID) }}
1746                         partend<<C>>
1747     
1748     rule mainboardinit<<C>>:
1749                         MAINBOARDINIT DIRPATH   {{ if (C): addcrt0include(DIRPATH)}}
1750
1751     rule initinclude<<C>>: 
1752                         INITINCLUDE 
1753                         STR 
1754                         DIRPATH                 {{ if (C): addinitinclude(STR, DIRPATH)}}
1755
1756     rule initobject<<C>>:
1757                         INITOBJECT DIRPATH      {{ if (C): addinitobject(DIRPATH)}}
1758
1759     rule object<<C>>:   OBJECT DIRPATH          {{ if (C): addobject(DIRPATH)}}
1760
1761     rule driver<<C>>:   DRIVER DIRPATH          {{ if (C): adddriver(DIRPATH)}}
1762
1763     rule smmobject<<C>>:
1764                         SMMOBJECT DIRPATH       {{ if (C): addsmmobject(DIRPATH)}}
1765
1766
1767     rule dir<<C>>:      DIR DIRPATH             {{ if (C): dodir(DIRPATH, 'Config.lb') }}
1768
1769     rule default<<C>>:  DEFAULT ID EQ value     {{ if (C): setdefault(ID, value, 0) }}
1770
1771     rule ldscript<<C>>: LDSCRIPT DIRPATH        {{ if (C): addldscript(DIRPATH) }}
1772
1773     rule iif<<C>>:      IF ID                   {{ c = lookup(ID) }}
1774                         (stmt<<C and c>>)* 
1775                         [ ELSE (stmt<<C and not c>>)* ]
1776                         END
1777
1778     rule makerule<<C>>: MAKERULE RULE           {{ if (C): addrule(RULE) }}
1779                         ( DEPENDS STR           {{ if (C): adddep(RULE, STR) }}
1780                         | ACTION STR            {{ if (C): addaction(RULE, STR) }}
1781                         )*
1782                         END
1783
1784     rule makedefine<<C>>:
1785                         MAKEDEFINE RAWTEXT      {{ if (C): adduserdefine(RAWTEXT) }}
1786
1787     rule addaction<<C>>:
1788                         ADDACTION ID STR        {{ if (C): addaction(ID, STR) }}
1789
1790     rule init<<C>>:     INIT DIRPATH            {{ if (C): addinit(DIRPATH) }}
1791
1792     rule field:         STR                     {{ return STR }}
1793
1794     rule register<<C>>: REGISTER field '=' STR  {{ if (C): addregister(field, STR) }}
1795
1796     rule enable<<C>>:                           {{ val = 1 }}
1797                         ( ON                    {{ val = 1 }}
1798                         | OFF                   {{ val = 0 }}
1799                         )                       {{ if(C): partstack.tos().set_enabled(val) }}
1800
1801     rule resource<<C>>:                         {{ type = "" }}
1802                         (  IO                   {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IO" }}
1803                         |   MEM                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_MEM" }}
1804                         |   IRQ                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IRQ" }}
1805                         |   DRQ                 {{ type = "IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_DRQ" }}
1806                         )
1807                         term '='                {{ index = term }}
1808                         term                    {{ value = term }}
1809                                                 {{ if (C): partstack.tos().add_resource(type, index, value) }}
1810     
1811                              
1812     rule resources<<C>>:                        {{ if (C): partstack.tos().start_resources() }}
1813                         ( resource<<C>> )*
1814                                                 {{ if (C): partstack.tos().end_resources() }}
1815             
1816     
1817     rule pci<<C>>:      PCI                     {{ if (C): devicepart('pci') }}
1818
1819                         HEX_NUM                 {{ slot = int(HEX_NUM,16) }}
1820                         '.' HEX_NUM             {{ function = int(HEX_NUM, 16) }}
1821                                                 {{ if (C): partstack.tos().addpcipath(slot, function) }}
1822     rule pci_domain<<C>>:       
1823                         PCI_DOMAIN              {{ if (C): devicepart('pci_domain') }}
1824                         HEX_NUM                 {{ pci_domain = int(HEX_NUM, 16) }}
1825                                                 {{ if (C): partstack.tos().addpci_domainpath(pci_domain) }}
1826
1827     rule pnp<<C>>:      PNP                     {{ if (C): devicepart('pnp') }}
1828                         HEX_NUM                 {{ port = int(HEX_NUM,16) }}
1829                         '.' HEX_NUM             {{ device = int(HEX_NUM, 16) }}
1830                                                 {{ if (C): partstack.tos().addpnppath(port, device) }}
1831                                                 
1832     rule i2c<<C>>:      I2C                     {{ if (C): devicepart('i2c') }}
1833                         HEX_NUM                 {{ device = int(HEX_NUM, 16) }}
1834                                                 {{ if (C): partstack.tos().addi2cpath(device) }}
1835
1836     rule apic<<C>>:     APIC                    {{ if (C): devicepart('apic') }}
1837                         HEX_NUM                 {{ apic_id = int(HEX_NUM, 16) }}
1838                                                 {{ if (C): partstack.tos().addapicpath(apic_id) }}
1839
1840     rule apic_cluster<<C>>: APIC_CLUSTER        {{ if (C): devicepart('apic_cluster') }}
1841                         HEX_NUM                 {{ cluster = int(HEX_NUM, 16) }}
1842                                                 {{ if (C): partstack.tos().addapic_clusterpath(cluster) }}
1843
1844     rule cpu<<C>>:      CPU                     {{ if (C): devicepart('cpu') }}
1845                         HEX_NUM                 {{ id = int(HEX_NUM, 16) }}
1846                                                 {{ if (C): partstack.tos().addcpupath(id) }}
1847
1848     rule cpu_bus<<C>>:  CPU_BUS                 {{ if (C): devicepart('cpu_bus') }}
1849                         HEX_NUM                 {{ id = int(HEX_NUM, 16) }}
1850                                                 {{ if (C): partstack.tos().addcpu_buspath(id) }}
1851
1852     rule dev_path<<C>>:
1853                         pci<<C>>                {{ return pci }}
1854                 |       pci_domain<<C>>         {{ return pci_domain }}
1855                 |       pnp<<C>>                {{ return pnp }}
1856                 |       i2c<<C>>                {{ return i2c }}
1857                 |       apic<<C>>               {{ return apic }}
1858                 |       apic_cluster<<C>>       {{ return apic_cluster }}
1859                 |       cpu<<C>>                {{ return cpu }}
1860                 |       cpu_bus<<C>>            {{ return cpu_bus }}
1861                 
1862     rule prtval:        expr                    {{ return str(expr) }}
1863                 |       STR                     {{ return STR }}
1864
1865     rule prtlist:       prtval                  {{ el = "%(" + prtval }}
1866                         ( "," prtval            {{ el = el + "," + prtval }}
1867                         )*                      {{ return el + ")" }}   
1868
1869     rule prtstmt<<C>>:  PRINT STR               {{ val = STR }}
1870                         [ "," prtlist           {{ val = val + prtlist }}
1871                         ]                       {{ if (C): print eval(val) }}
1872
1873     rule config<<C>>:   CONFIG PATH             {{ if (C): addconfig(PATH) }}
1874
1875     rule device<<C>>:   DEVICE dev_path<<C>>
1876                         enable<<C>>                     
1877                         resources<<C>>
1878                         partend<<C>> 
1879
1880     rule stmt<<C>>:     arch<<C>>               {{ return arch}}
1881                 |       addaction<<C>>          {{ return addaction }}
1882                 |       config<<C>>             {{ return config}}
1883                 |       default<<C>>            {{ return default}}
1884                 |       dir<<C>>                {{ return dir}}
1885                 |       driver<<C>>             {{ return driver }}
1886                 |       iif<<C>>                {{ return iif }}
1887                 |       init<<C>>               {{ return init }}
1888                 |       initinclude<<C>>        {{ return initinclude }}
1889                 |       initobject<<C>>         {{ return initobject }}
1890                 |       ldscript<<C>>           {{ return ldscript}}
1891                 |       mainboardinit<<C>>      {{ return mainboardinit }}
1892                 |       makedefine<<C>>         {{ return makedefine }}
1893                 |       makerule<<C>>           {{ return makerule }}
1894                 |       object<<C>>             {{ return object }}
1895                 |       option<<C>>             {{ return option }}
1896                 |       partdef<<C>>            {{ return partdef }}
1897                 |       prtstmt<<C>>            {{ return prtstmt }}
1898                 |       register<<C>>           {{ return register }}
1899                 |       device<<C>>             {{ return device }}
1900                 |       smmobject<<C>>          {{ return smmobject }}
1901
1902     # ENTRY for parsing Config.lb file
1903     rule cfgfile:       (uses<<1>>)* 
1904                         (stmt<<1>>)*
1905                         EOF                     {{ return 1 }}
1906
1907     rule cfgfile:       (uses<<1>>)* 
1908                         (stmt<<1>>)*
1909                         EOF                     {{ return 1 }}
1910
1911     rule usesid<<C>>:   ID                      {{ if (C): usesoption(ID) }}
1912
1913     rule uses<<C>>:     USES (usesid<<C>>)+
1914
1915     rule mainboardvariables:    (uses<<1>>)*
1916                                 (default<<1>>)*
1917                                 (option<<1>>)*
1918                                 END             {{ return 1}}
1919
1920     rule value:         STR                     {{ return dequote(STR) }} 
1921                 |       expr                    {{ return expr }}
1922                 |       DELEXPR                 {{ return DELEXPR }}
1923
1924     rule option<<C>>:   OPTION ID EQ value      {{ if (C): setoption(ID, value, 0) }}
1925
1926     rule opif<<C>>:     IF ID                   {{ c = lookup(ID) }}
1927                         (opstmt<<C and c>>)* 
1928                         [ ELSE (opstmt<<C and not c>>)* ] 
1929                         END
1930
1931     rule opstmt<<C>>:   option<<C>>
1932                 |       opif<<C>>
1933                 |       prtstmt<<C>>
1934
1935     rule payload<<C>>:  PAYLOAD DIRPATH         {{ if (C): payload(DIRPATH) }}
1936
1937     rule mainboard:
1938                         MAINBOARD PATH          {{ mainboardsetup(PATH) }}
1939
1940     rule romif<<C>>:    IF ID                   {{ c = lookup(ID) }}
1941                         (romstmt<<C and c>>)* 
1942                         [ ELSE (romstmt<<C and not c>>)* ]
1943                         END
1944
1945     rule romstmt<<C>>:  romif<<C>>
1946                 |       option<<C>>
1947                 |       payload<<C>>
1948
1949     rule romimage:      ROMIMAGE STR            {{ startromimage(dequote(STR)) }}
1950                         (romstmt<<1>>)*
1951                         END                     {{ endromimage() }}
1952
1953     rule roms:          STR                     {{ s = '[' + STR }}
1954                         ( STR                   {{ s = s + "," + STR }}
1955                         )*                      {{ return eval(s + ']') }}
1956
1957     rule buildrom:      BUILDROM DIRPATH expr roms      {{ addbuildrom(DIRPATH, expr, roms) }}
1958
1959     rule pci_vid:       VENDOR_ID EQ term       {{ return term }}
1960
1961     rule pci_did:       DEVICE_ID EQ term       {{ return term }}
1962
1963
1964     rule pci_rom:       PCI_ROM DIRPATH pci_vid pci_did {{ addpci_rom(DIRPATH, pci_vid, pci_did) }}
1965
1966     rule romstmts:      romimage 
1967                 |       buildrom
1968                 |       opstmt<<1>>
1969                 |       pci_rom
1970
1971     # ENTRY for parsing root part
1972     rule board:         {{ loadoptions("config", "Options.lb", "options") }}
1973                         TARGET DIRPATH          {{ target(DIRPATH) }}
1974                         mainboard
1975                         (romstmts)*             
1976                         EOF                     {{ return 1 }}
1977
1978     # ENTRY for parsing a delayed value
1979     rule delexpr:       "{" expr "}" EOF        {{ return expr }}
1980
1981     rule wrstr<<ID>>:   STR                     {{ setwrite(ID, dequote(STR)) }}
1982
1983     rule defstmts<<ID>>:                        {{ d = 0 }}
1984                         ( DEFAULT
1985                           ( value               {{ setdefault(ID, value, 1) }}
1986                           | NONE                {{ setnodefault(ID) }}
1987                           )                     {{ d = d | 1 }}
1988                         | FORMAT STR            {{ setformat(ID, dequote(STR)) }}
1989                         | EXPORT 
1990                           ( ALWAYS              {{ setexported(ID) }}
1991                           | USED                {{ setexportable(ID) }}
1992                           | NEVER               {{ setnoexport(ID) }}
1993                           )                     {{ d = d | 2 }}
1994                         | COMMENT STR           {{ setcomment(ID, dequote(STR)); d = d | 4 }}
1995                         | WRITE (wrstr<<ID>>)+
1996                         )+                      {{ return d }}
1997                 
1998     rule define:        DEFINE ID               {{ newoption(ID) }}
1999                         defstmts<<ID>> END      {{ validdef(ID, defstmts) }}
2000
2001     # ENTRY for parsing Options.lb file
2002     rule options:       (define)* EOF           {{ return 1 }}
2003 %%
2004
2005 #=============================================================================
2006 #               FILE OUTPUT 
2007 #=============================================================================
2008 def writemakefileheader(file, fname):
2009         file.write("# File: %s is autogenerated\n" % fname)
2010
2011 def writemakefilefooter(file, fname):
2012         file.write("\n\n%s: %s %s\n"
2013                 % (os.path.basename(fname), os.path.abspath(sys.argv[0]), top_config_file))
2014         file.write("\t(cd %s ; export PYTHONPATH=%s/util/newconfig ; python %s %s %s)\n\n"
2015                 % (os.getcwd(), treetop, sys.argv[0], sys.argv[1], sys.argv[2]))
2016
2017 def writemakefilesettings(path):
2018         """ Write Makefile.settings to seperate the settings
2019         from the actual makefile creation."""
2020
2021         global treetop, target_dir
2022
2023         filename = os.path.join(path, "Makefile.settings")
2024         print "Creating", filename
2025         file = safe_open(filename, 'w+')
2026         writemakefileheader(file, filename)
2027         file.write("TOP:=%s\n" % (treetop))
2028         file.write("TARGET_DIR:=%s\n" % target_dir)
2029         writemakefilefooter(file, filename)
2030         file.close()
2031
2032 def writeimagesettings(image):
2033         """Write Makefile.settings to seperate the settings
2034         from the actual makefile creation."""
2035
2036         global treetop
2037         global global_options_by_order
2038
2039         filename = os.path.join(image.gettargetdir(), "Makefile.settings")
2040         print "Creating", filename
2041         file = safe_open(filename, 'w+')
2042         writemakefileheader(file, filename)
2043         file.write("TOP:=%s\n" % (treetop))
2044         file.write("TARGET_DIR:=%s\n" % (image.gettargetdir()))
2045         file.write("\n")
2046         exported = []
2047         for o in global_exported_options:
2048                 exported.append(o)
2049         for o in image.exported_options:
2050                 if (not o in exported):
2051                         exported.append(o)
2052         for o in exported:
2053                 file.write("export %s:=" % o.name)
2054                 if (hasvalue(o.name, image)):
2055                         file.write("%s" % getformated(o.name, image))
2056                 file.write("\n")
2057         file.write("\n")
2058         file.write("export VARIABLES :=\n")
2059         for o in exported:
2060                 file.write("export VARIABLES += %s\n" % o.name)
2061         file.write("\n")
2062         # writemakefilefooter(file,filename)
2063         file.close()
2064
2065 # write the romimage makefile
2066 # let's try the Makefile
2067 # first, dump all the -D stuff
2068
2069 def writeimagemakefile(image):
2070         makefilepath = os.path.join(image.gettargetdir(), "Makefile")
2071         print "Creating", makefilepath
2072         file = safe_open(makefilepath, 'w+')
2073         writemakefileheader(file, makefilepath)
2074
2075         # main rule
2076         file.write("\nall: coreboot.rom\n\n")
2077         file.write(".PHONY: all\n\n")
2078         #file.write("include cpuflags\n")
2079         # Putting "include cpuflags" in the Makefile has the problem that the
2080         # cpuflags file would be generated _after_ we want to include it.
2081         # Instead, let make do the work of computing CPUFLAGS:
2082         file.write("# Get the value of TOP, VARIABLES, and several other variables.\n")
2083         file.write("include Makefile.settings\n\n")
2084         file.write("# Function to create an item like -Di586 or -DCONFIG_MAX_CPUS='1' or -Ui686\n")
2085         file.write("D_item = $(shell echo '$(if $(subst undefined,,$(origin $1)),\\#define $1$(if $($1), $($1),),\\#undef $1)' >> settings.h)\n\n")
2086         file.write("# Compute the value of CPUFLAGS here during make's first pass.\n")
2087         file.write("CPUFLAGS := $(strip $(shell echo '/* autogenerated */' > settings.h)$(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))--include=settings.h)\n\n")
2088
2089         for i in image.getuserdefines():
2090                 file.write("%s\n" %i)
2091         file.write("\n")
2092
2093         # print out all the object dependencies
2094         file.write("\n# object dependencies (objectrules:)\n")
2095         file.write("INIT-OBJECTS :=\n")
2096         file.write("OBJECTS :=\n")
2097         file.write("DRIVER :=\n")
2098         file.write("\nSOURCES :=\n")
2099         for irule, init in image.getinitobjectrules().items():
2100                 i_name = init[0]
2101                 i_source = init[1]
2102                 file.write("INIT-OBJECTS += %s\n" % (i_name))
2103                 file.write("SOURCES += %s\n" % (i_source))
2104
2105         for objrule, obj in image.getobjectrules().items():
2106                 obj_name = obj[0]
2107                 obj_source = obj[1]
2108                 file.write("OBJECTS += %s\n" % (obj_name))
2109                 file.write("SOURCES += %s\n" % (obj_source))
2110
2111         for srule, smm in image.getsmmobjectrules().items():
2112                 s_name = smm[0]
2113                 s_source = smm[1]
2114                 file.write("SMM-OBJECTS += %s\n" % (s_name))
2115                 file.write("SOURCES += %s\n" % (s_source))
2116
2117
2118         # for chip_target.c
2119         file.write("OBJECTS += static.o\n")
2120         file.write("SOURCES += static.c\n")
2121
2122         for driverrule, driver in image.getdriverrules().items():
2123                 obj_name = driver[0]
2124                 obj_source = driver[1]
2125                 file.write("DRIVER += %s\n" % (obj_name))
2126                 file.write("SOURCES += %s\n" % (obj_source))
2127
2128         # Print out all ldscript.ld dependencies.
2129         file.write("\n# ldscript.ld dependencies:\n")
2130         file.write("LDSUBSCRIPTS-1 := \n" )
2131         for script in image.getldscripts():
2132                 file.write("LDSUBSCRIPTS-1 += %s\n" % topify(script))
2133
2134         # Print out the dependencies for crt0_includes.h
2135         file.write("\n# Dependencies for crt0_includes.h\n")
2136         file.write("CRT0_INCLUDES:=\n")
2137         for inc in image.getinitincludes():
2138                 if (local_path.match(inc)):
2139                         file.write("CRT0_INCLUDES += %s\n" % inc)
2140                 else:
2141                         file.write("CRT0_INCLUDES += $(TOP)/src/%s\n" % inc)
2142
2143         # Print out the user defines.
2144         file.write("\n# userdefines:\n")
2145                 
2146         # Print out the base rules.
2147         # Need to have a rule that counts on 'all'.
2148         file.write("\n# mainrulelist:")
2149
2150         # Print out any user rules.
2151         file.write("\n# From makerule or docipl commands:\n")
2152
2153         file.write("\n# initobjectrules:\n")
2154         for irule, init in image.getinitobjectrules().items():
2155                 source = topify(init[1])
2156                 type = init[2]
2157                 if (type  == 'S'):
2158                         # for .S, .o depends on .s
2159                         file.write("%s: %s.s\n" % (init[0], init[3]))
2160                         file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n")
2161                         # and .s depends on .S
2162                         file.write("%s.s: %s\n" % (init[3], source))
2163                         # Note: next 2 lines are ONE output line!
2164                         file.write("\t$(CPP) $(CPPFLAGS) $< ")
2165                         file.write(">$@.new && mv $@.new $@\n")
2166                 else:
2167                         file.write("%s: %s\n" % (init[0], source))
2168                         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2169
2170         file.write("\n# objectrules:\n")
2171         for objrule, obj in image.getobjectrules().items():
2172                 source = topify(obj[1])
2173                 type = obj[2]
2174                 if (type  == 'S'):
2175                         # for .S, .o depends on .s
2176                         file.write("%s: %s.s\n" % (obj[0], obj[3]))
2177                         file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n")
2178                         # and .s depends on .S
2179                         file.write("%s.s: %s\n" % (obj[3], source))
2180                         # Note: next 2 lines are ONE output line!
2181                         file.write("\t$(CPP) $(CPPFLAGS) $< ")
2182                         file.write(">$@.new && mv $@.new $@\n")
2183                 else:
2184                         file.write("%s: %s\n" % (obj[0], source))
2185                         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2186                 #file.write("%s\n" % objrule[2])
2187
2188         for driverrule, driver in image.getdriverrules().items():
2189                 source = topify(driver[1])
2190                 file.write("%s: %s\n" % (driver[0], source))
2191                 file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2192                 #file.write("%s\n" % objrule[2])
2193
2194         file.write("\n# smmobjectrules:\n")
2195         for irule, smm in image.getsmmobjectrules().items():
2196                 source = topify(smm[1])
2197                 type = smm[2]
2198                 if (type  == 'S'):
2199                         # for .S, .o depends on .s
2200                         file.write("%s: %s.s\n" % (smm[0], smm[3]))
2201                         file.write("\t$(CC) -c $(CPU_OPT) -o $@ $<\n")
2202                         # and .s depends on .S
2203                         file.write("%s.s: %s\n" % (smm[3], source))
2204                         # Note: next 2 lines are ONE output line!
2205                         file.write("\t$(CPP) $(CPPFLAGS) $< ")
2206                         file.write(">$@.new && mv $@.new $@\n")
2207                 else:
2208                         file.write("%s: %s\n" % (smm[0], source))
2209                         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2210
2211         # special rule for chip_target.c
2212         file.write("static.o: static.c\n")
2213         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
2214
2215         # Print out the rules that will make cause the files
2216         # generated by NLBConfig.py to be remade if any dependencies change.
2217
2218         file.write("\n# Remember the automatically generated files\n")
2219         file.write("GENERATED:=\n")
2220         for genfile in ['Makefile',
2221                         'nsuperio.c',
2222                         'static.c',
2223                         'corebootDoc.config' ]:
2224                 file.write("GENERATED += %s\n" % genfile)
2225         file.write("GENERATED += %s\n" % image.getincludefilename())
2226
2227         keys = global_options_by_order
2228         keys.sort()
2229         file.write("\necho:\n")
2230         for key in keys:
2231                  file.write("\t@echo %s='$(%s)'\n"% (key,key))
2232
2233         for i, m in image.getmakerules().items():
2234                 file.write("%s: " %i)
2235                 for i in m.dependency:
2236                         file.write("%s " % i)
2237                 file.write("\n")
2238                 for i in m.actions:
2239                         file.write("\t%s\n" % i)
2240         writemakefilefooter(file, makefilepath)
2241         file.close()
2242
2243 #
2244 def writemakefile(path):
2245         global rommapping
2246         global bootblocksize
2247         makefilepath = os.path.join(path, "Makefile")
2248         print "Creating", makefilepath
2249         file = safe_open(makefilepath, 'w+')
2250         writemakefileheader(file, makefilepath)
2251
2252         # Hack to get the necessary settings (CONFIG_CBFS):
2253         file.write("include %s/Makefile.settings\n\n" % romimages.keys()[0])
2254
2255         # main rule
2256         file.write("ifeq \"$(CONFIG_CBFS)\" \"1\"\n")
2257         file.write("\nall: ")
2258         for i in buildroms:
2259                 file.write(" %sfs" % i.name)
2260         file.write("\n")
2261         file.write("else")
2262         file.write("\nall: ")
2263         for i in buildroms:
2264                 file.write(" %s" % i.name)
2265         file.write("\n")
2266         file.write("endif\n\n")
2267
2268         # cbfstool rules
2269         file.write("\ncbfstool:\n\tmkdir -p tools/lzma\n\t$(MAKE) -C $(TOP)/util/cbfstool obj=$(shell pwd)\n\n")
2270
2271         file.write("include Makefile.settings\n\n")
2272         for i, o in romimages.items():
2273                 file.write("%s/coreboot.rom:\n" % o.getname())
2274                 file.write("\tif (cd %s; \\\n" % o.getname())
2275                 file.write("\t\t$(MAKE) coreboot.rom)\\\n")
2276                 file.write("\tthen true; else exit 1; fi;\n\n")
2277         file.write("clean: ")
2278         for i in romimages.keys():
2279                 file.write(" %s-clean" % i)
2280         file.write(" base-clean")
2281         file.write("\n\n")
2282         for i, o in romimages.items():
2283                 file.write("%s-clean:\n" % o.getname())
2284                 file.write("\t(cd %s; $(MAKE) clean)\n\n" % o.getname())
2285         file.write("base-clean:\n")
2286         file.write("\trm -f romcc*\n\n")
2287
2288         for i in buildroms:
2289                 file.write("%s:" % i.name)
2290                 for j in i.roms:
2291                         file.write(" %s/coreboot.rom " % j)
2292                 file.write("\n")
2293                 file.write("\t cat ")
2294                 for j in i.roms:
2295                         file.write(" %s/coreboot.rom " % j)
2296                 file.write("> %s\n\n" %i.name)
2297                 # build the bootblock here as well. 
2298                 file.write("\n")
2299                 file.write("\t cat ")
2300                 for j in i.roms:
2301                         file.write(" %s/coreboot.strip " % j)
2302                 file.write("> %s.bootblock\n\n" %i.name)
2303
2304         romsize = getoption("ROM_SIZE", image)
2305         # i.name? That can not be right, can it? 
2306         file.write("%sfs: %s cbfstool\n" %(i.name,i.name));
2307         file.write("\trm -f coreboot.cbfs\n");
2308         file.write("\t./cbfstool %sfs create %s %s %s.bootblock\n" % (i.name, romsize, bootblocksize, i.name))
2309         for i in pciroms:
2310                 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))
2311         for i in buildroms:
2312                 for j in i.roms:
2313                         #failover is a hack that will go away soon. 
2314                         if (j != "failover") and (rommapping[j] != "/dev/null"):
2315                                 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))
2316                 file.write("\t ./cbfstool %sfs print\n" % i.name)
2317
2318         file.write(".PHONY: all clean cbfstool")
2319         for i in romimages.keys():
2320                 file.write(" %s-clean" % i)
2321         for i, o in romimages.items():
2322                 file.write(" %s/coreboot.rom" % o.getname())
2323         file.write("\n\n")
2324
2325         writemakefilefooter(file, makefilepath)
2326         file.close()
2327
2328 def writeinitincludes(image):
2329         global include_pattern
2330         filepath = os.path.join(image.gettargetdir(), image.getincludefilename())
2331         print "Creating", filepath
2332         outfile = safe_open(filepath, 'w+')
2333         if (image.newformat()):
2334                 infile = safe_open(image.getinitfile(), 'r')
2335
2336                 line = infile.readline()
2337                 while (line):
2338                         p = include_pattern.match(line)
2339                         if (p):
2340                                 for i in image.getinitincludes():
2341                                         inc = image.getinitinclude(i)
2342                                         if (inc.getstring() == p.group(1)):
2343                                                 outfile.write("#include \"%s\"\n" % inc.getpath())
2344                         else:
2345                                 outfile.write(line)
2346                         line = infile.readline()
2347
2348                 infile.close()
2349         else:
2350                 for i in image.getinitincludes():
2351                         outfile.write("#include <%s>\n" % i)
2352         outfile.close()
2353
2354 def writeldoptions(image):
2355         """Write ldoptions file."""
2356         filename = os.path.join(image.gettargetdir(), "ldoptions")
2357         print "Creating", filename
2358         file = safe_open(filename, 'w+')
2359         for o in global_exported_options:
2360                 if (hasvalue(o.name, image) and IsInt(getoption(o.name, image))):
2361                         file.write("%s = %s;\n" % (o.name, getformated(o.name, image)))
2362         for o in image.exported_options:
2363                 if (not o in global_exported_options and hasvalue(o.name, image) and IsInt(getoption(o.name, image))):
2364                         file.write("%s = %s;\n" % (o.name, getformated(o.name, image)))
2365         file.close()
2366
2367 def dumptree(part, lvl):
2368         debug.info(debug.dumptree, "DUMPTREE ME is")
2369         part.dumpme(lvl)
2370         # dump the siblings -- actually are there any? not sure
2371         # siblings are:
2372         debug.info(debug.dumptree, "DUMPTREE SIBLINGS are")
2373         kid = part.next_sibling
2374         while (kid):
2375                 kid.dumpme(lvl)
2376                 kid = kid.next_sibling
2377         # dump the kids
2378         debug.info(debug.dumptree, "DUMPTREE KIDS are")
2379         #for kid in part.children:
2380         if (part.children):
2381                 dumptree(part.children, lvl+1)
2382         kid = part.next_sibling
2383         while (kid):
2384                 if (kid.children):
2385                         dumptree(kid.children, lvl + 1)
2386                 kid = kid.next_sibling
2387         debug.info(debug.dumptree, "DONE DUMPTREE")
2388
2389 def writecode(image):
2390         filename = os.path.join(img_dir, "static.c")
2391         print "Creating", filename
2392         file = safe_open(filename, 'w+')
2393         file.write("#include <device/device.h>\n")
2394         file.write("#include <device/pci.h>\n")
2395         for path in image.getconfigincludes().values():
2396                 file.write("#include \"%s\"\n" % path)
2397         file.write("\n/* pass 0 */\n")
2398         gencode(image.getroot(), file, 0)
2399         file.write("\n/* pass 1 */\n")
2400         gencode(image.getroot(), file, 1)
2401         file.close()
2402
2403 def gencode(part, file, pass_num):
2404         debug.info(debug.gencode, "GENCODE ME is")
2405         part.gencode(file, pass_num)
2406         # dump the siblings -- actually are there any? not sure
2407         debug.info(debug.gencode, "GENCODE SIBLINGS are")
2408         kid = part.next_sibling
2409         while (kid):
2410                 kid.gencode(file, pass_num)
2411                 kid = kid.next_sibling
2412         # now dump the children 
2413         debug.info(debug.gencode, "GENCODE KIDS are")
2414         if (part.children):
2415                 gencode(part.children, file, pass_num)
2416         kid = part.next_sibling
2417         while (kid):
2418                 if (kid.children):
2419                         gencode(kid.children, file, pass_num)
2420                 kid = kid.next_sibling
2421         debug.info(debug.gencode, "DONE GENCODE")
2422
2423 def writegraph(image):
2424         filename = os.path.join(img_dir, "static.dot")
2425         print "Creating", filename
2426         file = safe_open(filename, 'w+')
2427         file.write("digraph devicetree {\n")
2428         file.write("    rankdir=LR\n")
2429         genranks(image.getroot(), file, 0)
2430         gennodes(image.getroot(), file)
2431         gengraph(image.getroot(), file)
2432         file.write("}\n")
2433         file.close()
2434
2435 def genranks(part, file, level):
2436         #file.write("   # Level %d\n" % level )
2437         file.write("    { rank = same; \"dev_%s_%d\"" % (part.type_name,part.instance ))
2438         sib = part.next_sibling
2439         while (sib):
2440                 file.write("; \"dev_%s_%d\"" % (sib.type_name, sib.instance))
2441                 sib = sib.next_sibling
2442         file.write("}\n" )
2443         # now dump the children 
2444         if (part.children):
2445                 genranks(part.children, file, level + 1)
2446
2447         kid = part.next_sibling
2448         while (kid):
2449                 if (kid.children):
2450                         genranks(kid.children, file, level + 1)
2451                 kid = kid.next_sibling
2452
2453
2454 def gennodes(part, file):
2455         file.write("    dev_%s_%d[shape=record, label=\"%s\"];\n" % (part.type_name,part.instance,part.graph_name() ))
2456         sib = part.next_sibling
2457         while (sib):
2458                 file.write("    dev_%s_%d[shape=record, label=\"%s\"];\n" % (sib.type_name,sib.instance,sib.graph_name() ))
2459                 sib = sib.next_sibling
2460         # now dump the children
2461         if (part.children):
2462                 gennodes(part.children, file)
2463
2464         kid = part.next_sibling
2465         while (kid):
2466                 if (kid.children):
2467                         gennodes(kid.children, file)
2468                 kid = kid.next_sibling
2469
2470
2471 def gengraph(part, file):
2472         if (part.parent != part):
2473                 file.write("    dev_%s_%d -> dev_%s_%d;\n" % \
2474                                 (part.parent.type_name, part.parent.instance, \
2475                                  part.type_name, part.instance ))
2476         sib = part.next_sibling
2477         while (sib):
2478                 file.write("    dev_%s_%d -> dev_%s_%d;\n" % \
2479                                 (sib.parent.type_name, sib.parent.instance, \
2480                                  sib.type_name, sib.instance ))
2481                 sib = sib.next_sibling
2482
2483         kid = part.next_sibling
2484         while (kid):
2485                 if (kid.children):
2486                         gengraph(kid.children, file)
2487                 kid = kid.next_sibling
2488
2489         if (part.children):
2490                 gengraph(part.children, file)
2491
2492 def verifyparse():
2493         """Add any run-time checks to verify that parsing the configuration
2494         was successful"""
2495
2496         for image in romimages.values():
2497                 print("Verifying ROMIMAGE %s" % image.name)
2498                 if (image.newformat() and image.getinitfile() == ''):
2499                         fatal("An init file must be specified")
2500                 for op in image.exported_options:
2501                         if (getoptionvalue(op.name, op, image) == 0 and getoptionvalue(op.name, op, 0) == 0):
2502                                 warning("Exported option %s has no value (check Options.lb)" % op.name);
2503         print("Verifing global options")
2504         for op in global_exported_options:
2505                 if (getoptionvalue(op.name, op, 0) == 0):
2506                         notice("Exported option %s has no value (check Options.lb)" % op.name);
2507                         
2508 #=============================================================================
2509 #               MAIN PROGRAM
2510 #=============================================================================
2511 if __name__=='__main__':
2512         from sys import argv
2513         if (len(argv) < 3):
2514                 fatal("Args: <file> <path to coreboot>")
2515
2516         top_config_file = os.path.abspath(sys.argv[1])
2517
2518         treetop = os.path.abspath(sys.argv[2])
2519
2520         # Now read in the customizing script...
2521         loc.push(argv[1])
2522         fp = safe_open(argv[1], 'r')
2523         if (not parse('board', fp.read())):
2524                 fatal("Could not parse file")
2525         loc.pop()
2526
2527         verifyparse()
2528
2529         # no longer need to check if an options has been used
2530         alloptions = 1
2531
2532         for image_name, image in romimages.items():
2533                 if (debug.level(debug.dumptree)):
2534                         debug.info(debug.dumptree, "DEVICE TREE:")
2535                         dumptree(image.getroot(), 0)
2536
2537                 img_dir = image.gettargetdir()
2538                 if not os.path.isdir(img_dir):
2539                         print "Creating directory %s" % img_dir
2540                         os.makedirs(img_dir)
2541
2542                 for objrule, obj in image.getobjectrules().items():
2543                         sub_dir = img_dir + '/' + os.path.dirname(obj[0])
2544                         if not os.path.isdir(sub_dir):
2545                                 print "Creating sub directory %s" % sub_dir
2546                                 os.makedirs(sub_dir)
2547
2548                 for driverrule, driver in image.getdriverrules().items():
2549                         sub_dir = img_dir + '/' + os.path.dirname(driver[0])
2550                         if not os.path.isdir(sub_dir):
2551                                 print "Creating sub directory %s" % sub_dir
2552                                 os.makedirs(sub_dir)
2553
2554                 for srule, smm in image.getsmmobjectrules().items():
2555                         sub_dir = img_dir + '/' + os.path.dirname(smm[0])
2556                         if not os.path.isdir(sub_dir):
2557                                 print "Creating sub directory %s" % sub_dir
2558                                 os.makedirs(sub_dir)
2559
2560                 for irule, init in image.getinitobjectrules().items():
2561                         sub_dir = img_dir + '/' + os.path.dirname(init[0])
2562                         if not os.path.isdir(sub_dir):
2563                                 print "Creating sub directory %s" % sub_dir
2564                                 os.makedirs(sub_dir)
2565
2566                 if (debug.level(debug.dump)):
2567                         for i in image.getinitincludes():
2568                                 debug.info(debug.dump, "crt0include file %s" % i)
2569                         for i in image.getdriverrules().keys():
2570                                 debug.info(debug.dump, "driver file %s" % i)
2571                         for i in image.getldscripts():
2572                                 debug.info(debug.dump, "ldscript file %s" % i)
2573                         for i, m in image.getmakerules().items():
2574                                 debug.info(debug.dump, " makerule %s dep %s act %s" % (i, m.dependency, m.actions))
2575
2576                 writecode(image)
2577                 writeimagesettings(image)
2578                 writeinitincludes(image)
2579                 writeimagemakefile(image)
2580                 writeldoptions(image)
2581                 writegraph(image)
2582
2583         writemakefilesettings(target_dir)
2584         writemakefile(target_dir)
2585
2586         sys.exit(0)