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