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