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