chip stuff
[coreboot.git] / util / newconfig / config.g
1 import sys
2 import os
3 import re
4 import string
5
6 warnings = 0
7 errors = 0
8
9 target_dir = ''
10 target_name = ''
11 treetop = ''
12 global_options = {}
13 global_options_by_order = []
14 global_option_values = {}
15 global_uses_options = {}
16 romimages = {}
17 buildroms = []
18 curimage = 0
19 alloptions = 0 # override uses at top level
20
21 local_path = re.compile(r'^\.')
22 include_pattern = re.compile(r'%%([^%]+)%%')
23
24 # -----------------------------------------------------------------------------
25 #                    Utility Classes
26 # -----------------------------------------------------------------------------
27
28 class stack:
29         """Used to keep track of the current part or dir"""
30         class __stack_iter:
31                 def __init__ (self, stack):
32                         self.index = 0
33                         self.len = len(stack)
34                         self.stack = stack
35
36                 def __iter__ (self):
37                         return self
38
39                 def next (self):
40                         if (self.index < self.len):
41                                 s = self.stack[self.index]
42                                 self.index = self.index + 1
43                                 return s
44                         raise StopIteration
45
46         def __init__ (self):
47                 self.stack = []
48
49         def __len__ (self):
50                 return len(self.stack)
51
52         def __getitem__ (self, i):
53                 try:
54                         return self.stack[i]
55                 except IndexError:
56                         return 0
57
58         def __iter__ (self):
59                 return self.__stack_iter(self.stack)
60
61         def push(self, part):
62                 self.stack.append(part)
63
64         def pop(self):
65                 try:
66                         return self.stack.pop()
67                 except IndexError:
68                         return 0
69
70         def tos(self):
71                 try:
72                         return self.stack[-1]
73                 except IndexError:
74                         return 0
75
76         def empty(self):
77                 return (len(self.stack) == 0)
78 partstack = stack()
79 dirstack = stack()
80
81 class debug_info:
82         none = 0
83         gencode = 1
84         dumptree = 2
85         object = 3
86         dict = 4
87         statement = 5
88         dump = 6
89
90         def __init__(self, *level):
91                 self.__level = level
92
93         def setdebug(self, *level):
94                 self.__level = level
95
96         def level(self, level):
97                 return level in self.__level
98
99         def info(self, level, str):
100                 if level in self.__level:
101                         print str
102
103 global debug
104 debug = debug_info(debug_info.none)
105
106 # -----------------------------------------------------------------------------
107 #                    Error Handling
108 # -----------------------------------------------------------------------------
109
110 class location:
111         """Used to keep track of our current location while parsing
112         configuration files"""
113         class __place:
114                 def __init__(self, file, line, command):
115                         self.file = file
116                         self.line = line
117                         self.command = command
118                 def next_line(self, command):
119                         self.line = self.line + 1
120                         self.command = command
121                 def at(self):
122                         return "%s:%d" % (self.file, self.line)
123         
124         def __init__ (self):
125                 self.stack = stack()
126
127         def __str__ (self):
128                 s = ''
129                 for p in self.stack:
130                         if (s == ''):
131                                 s = p.at()
132                         else:
133                                 s = s + '\n' + p.at()
134                 return s
135
136         def file(self):
137                 return self.stack.tos().file
138
139         def line(self):
140                 return self.stack.tos().line
141
142         def command(self):
143                 return self.stack.tos().command
144
145         def push(self, file):
146                 self.stack.push(self.__place(os.path.normpath(file), 0, ""))
147
148         def pop(self):
149                 self.stack.pop()
150
151         def next_line(self, command):
152                 self.stack.tos().next_line(command)
153
154         def at(self):
155                 return self.stack.tos().at()
156 loc = location()
157
158 def error(string):      
159         """Print error message"""
160         global errors, loc
161         errors = errors + 1
162         print "===> ERROR: %s" % string
163         print "%s" % loc
164
165 def fatal(string):      
166         """Print error message and exit"""
167         error(string)
168         exitiferrors()
169
170 def warning(string):
171         """Print warning message"""
172         global warnings, loc
173         warnings = warnings + 1
174         print "===> Warning: %s" % string
175         print "%s" % loc
176
177 def exitiferrors():
178         """Exit parser if an error has been encountered"""
179         if (errors != 0):
180                 sys.exit(1)
181
182 # -----------------------------------------------------------------------------
183 #                    Main classes
184 # -----------------------------------------------------------------------------
185
186 class romimage:
187         """A rom image is the ultimate goal of linuxbios"""
188         def __init__ (self, name):
189                 self.name = name
190                 self.arch = ''
191                 self.payload = ''
192                 self.initfile = ''
193                 self.makebaserules = {}
194                 self.objectrules = {}
195                 self.initobjectrules = {}
196                 self.driverrules = {}
197                 self.ldscripts = []
198                 self.userdefines = []
199                 self.initincludes = {}
200                 self.useinitincludes = 0 # transitional
201                 self.partinstance = 0
202                 self.root = 0
203                 self.target_dir = ''
204                 self.values = {} # values of options set in romimage
205
206         def getname(self):
207                 return self.name
208
209         def getvalues(self):
210                 return self.values
211
212         def setarch(self, arch):
213                 self.arch = arch
214
215         def setpayload(self, payload):
216                 self.payload = payload
217
218         def setinitfile(self, initfile):
219                 self.initfile = initfile
220
221         def getinitfile(self):
222                 return self.initfile
223
224         def addmakerule(self, id):
225                 o = getdict(self.makebaserules, id)
226                 if (o):
227                         print "Warning, rule %s previously defined" % id
228                 o = makerule(id)
229                 setdict(self.makebaserules, id, o)
230
231         def getmakerules(self):
232                 return self.makebaserules
233
234         def getmakerule(self, id):
235                 o = getdict(self.makebaserules, id)
236                 if (o):
237                         return o
238                 fatal("No such make rule \"%s\"" % id);
239
240         def addmakeaction(self, id, str):
241                 o = getdict(self.makebaserules, id)
242                 if (o):
243                         a = dequote(str)
244                         o.addaction(a)
245                         return
246                 fatal("No such rule \"%s\" for addmakeaction" % id);
247
248         def addmakedepend(self, id, str):
249                 o = getdict(self.makebaserules, id)
250                 if (o):
251                         a = dequote(str)
252                         o.adddependency(a)
253                         return
254                 fatal("No such rule \"%s\" for addmakedepend" % id);
255
256         # this is called with an an object name. 
257         # the easiest thing to do is add this object to the current 
258         # component.
259         # such kludgery. If the name starts with '.' then make the 
260         # dependency be on ./thing.x gag me.
261         def addobjectdriver(self, dict, object_name):
262                 global dirstack
263                 suffix = object_name[-2:]
264                 if (suffix == '.o'):
265                         suffix = '.c'
266                 base = object_name[:-2]
267                 if (object_name[0] == '.'):
268                         source = base + suffix
269                 else:
270                         source = os.path.join(dirstack.tos(), base + suffix)
271                 object = base + '.o'
272                 debug.info(debug.object, "add object %s source %s" % (object_name, source))
273                 l = getdict(dict, base)
274                 if (l):
275                         print "Warning, object/driver %s previously defined" % base
276                 setdict(dict, base, [object, source])
277
278         def addinitobjectrule(self, name):
279                 self.addobjectdriver(self.initobjectrules, name)
280
281         def addobjectrule(self, name):
282                 self.addobjectdriver(self.objectrules, name)
283
284         def adddriverrule(self, name):
285                 self.addobjectdriver(self.driverrules, name)
286
287         def getinitobjectrules(self):
288                 return self.initobjectrules
289
290         def getinitobjectrule(self, name):
291                 o = getdict(self.initobjectrules, name)
292                 if (o):
293                         return o
294                 fatal("No such init object rule \"%s\"" % name);
295
296         def getobjectrules(self):
297                 return self.objectrules
298
299         def getobjectrule(self, name):
300                 o = getdict(self.objectrules, name)
301                 if (o):
302                         return o
303                 fatal("No such object rule \"%s\"" % name);
304
305         def getdriverrules(self):
306                 return self.driverrules
307
308         def getdriverrule(self, name):
309                 o = getdict(self.driverrules, name)
310                 if (o):
311                         return o
312                 fatal("No such driver rule \"%s\"" % name);
313
314         def addldscript(self, path):
315                 self.ldscripts.append(path)
316
317         def getldscripts(self):
318                 return self.ldscripts
319
320         def adduserdefine(self, str):
321                 self.userdefines.append(str)
322
323         def getuserdefines(self):
324                 return self.userdefines
325
326         def addinitinclude(self, str, path):
327                 if (str != 0):
328                         self.useinitincludes = 1
329
330                 debug.info(debug.object, "ADDCRT0: %s -> %s" % (str, path))
331                 o = getdict(self.initincludes, path)
332                 if (o):
333                         print "Warning, init include for %s previously defined" % path
334                 o = initinclude(str, path)
335                 setdict(self.initincludes, path, o)
336
337         def getinitincludes(self):
338                 return self.initincludes
339
340         def getinitinclude(self, path):
341                 o = getdict(self.initincludes, path)
342                 if (o):
343                         return o
344                 fatal("No such init include \"%s\"" % path);
345
346         def getincludefilename(self):
347                 if (self.useinitincludes):
348                         return "crt0.S"
349                 else:
350                         return "crt0_include.h"
351         
352         def newformat(self):
353                 return self.useinitincludes
354
355         def numparts(self):
356                 return self.partinstance
357
358         def newpartinstance(self):
359                 i = self.partinstance
360                 self.partinstance = self.partinstance + 1
361                 return i
362
363         def setroot(self, part):
364                 self.root = part
365
366         def getroot(self):
367                 return self.root
368
369         def settargetdir(self, path):
370                 self.targetdir = path
371
372         def gettargetdir(self):
373                 return self.targetdir
374
375 class buildrom:
376         """A buildrom statement"""
377         def __init__ (self, size, roms):
378                 self.size = size
379                 self.roms = roms
380
381 class initinclude:
382         """include file for initialization code"""
383         def __init__ (self, str, path):
384                 self.string = str
385                 self.path = path
386
387         def getstring(self):
388                 return self.string
389
390         def getpath(self):
391                 return self.path
392
393 class makerule:
394         """Rule to be included in Makefile"""
395         def __init__ (self, target):
396                 self.target = target
397                 self.dependency = []
398                 self.actions = []
399
400         def addaction(self, action):
401                 self.actions.append(action)
402
403         def adddependency(self, dependency):
404                 self.dependency.append(dependency)
405
406         def gtarget(self):
407                 return self.target
408
409         def gdependency(self):
410                 return self.dependency
411
412         def gaction(self):
413                 return self.actions
414
415 class option:
416         """Configuration option"""
417         def __init__ (self, name):
418                 self.name = name        # name of option
419                 self.loc = 0            # current location
420                 self.set = 0            # option has been set
421                 self.used = 0           # option has been set
422                 self.default = 0        # option has default value (otherwise
423                                         # it is undefined)
424                 self.comment = ''       # description of option
425                 self.exportable = 0     # option is able to be exported
426                 self.exported = 0       # option is exported
427                 self.defined = 0        # option has a value
428                 self.format = '%s'      # option print format
429
430         def setvalue(self, value, values, loc):
431                 self.set = 1
432                 self.defined = 1
433                 self.loc = loc
434                 #self.value = value
435                 setdict(values, self.name, value)
436
437         def getvalue(self, image, values):
438                 global curimage
439                 v = getdict(values, self.name)
440                 if (v == 0):
441                         return 0
442                 val = v.contents()
443                 if (not (type(val) is str)):
444                         return v
445                 if (val == '' or val[0] != '{'):
446                         return v
447                 s = curimage
448                 curimage = image
449                 val = parse('delexpr', val)
450                 curimage = s
451                 # TODO: need to check for parse errors!
452                 return option_value(val)
453
454         def setdefault(self, value, loc):
455                 global global_option_values
456                 if (self.default):
457                         fatal("Error: default value for %s already set" % self.name)
458                 setdict(global_option_values, self.name, value)
459                 self.defined = 1
460                 self.default = 1
461                 self.loc = loc
462
463         def setnodefault(self, loc):
464                 self.default = 1
465                 self.defined = 0
466                 self.loc = loc
467
468         def where(self):
469                 return self.loc
470
471         def setcomment(self, comment, loc):
472                 if (self.comment != ''):
473                         print "%s: " % self.name
474                         print "Attempt to modify comment at %s" % loc 
475                         return
476                 self.comment = comment
477
478         def setexportable(self):
479                 self.exportable = 1
480
481         def setexported(self):
482                 self.exportable = 1
483                 self.exported = 1
484
485         def setnoexport(self):
486                 self.exportable = 0
487                 self.exported = 0
488
489         def setformat(self, fmt):
490                 self.format = fmt
491
492         def getformat(self):
493                 return self.format
494
495         def setused(self):
496                 if (self.exportable):
497                         self.exported = 1
498                 self.used = 1
499
500         def isexported(self):
501                 return (self.exported and self.defined)
502
503 #       def isdefined(self):
504 #               return (self.defined)
505
506         def isset(self):
507                 return (self.set)
508
509 #       def isused(self):
510 #               return (self.used)
511
512 class option_value:
513         """Value of a configuration option"""
514         def __init__(self, value):
515                 self.value = value
516
517         def contents(self):
518                 return self.value
519
520 class partobj:
521         """A configuration part"""
522         def __init__ (self, image, dir, parent, type, name):
523                 debug.info(debug.object, "partobj dir %s parent %s type %s" %(dir,parent,type))
524                 self.image = image
525                 self.children = 0
526                 self.siblings = 0
527                 self.initcode = []
528                 self.registercode = []
529                 # sibling is not a list. 
530                 self.type = type
531                 self.objects = []
532                 self.dir = dir
533                 self.irq = 0
534                 self.instance = image.newpartinstance()
535                 self.flatten_name = flatten_name(type + "/" + name)
536                 debug.info(debug.object, "INSTANCE %d" % self.instance)
537                 self.devfn = 0  
538                 self.private = 0        
539                 self.uses_options = {}
540                 # chip initialization. If there is a chip.h in the 
541                 # directory, generate the structs etc. to 
542                 # initialize the code
543                 if (os.path.exists(dir + "/" + "chip.h")): 
544                         self.chipconfig = 1
545                 else:
546                         self.chipconfig = 0
547                 
548                 if (parent):
549                         debug.info(debug.gencode, "add to parent")
550                         self.parent   = parent
551                         # add current child as my sibling, 
552                         # me as the child.
553                         if (parent.children):
554                                 debug.info(debug.gencode, "add %s (%d) as sibling" % (parent.children.dir, parent.children.instance))
555                                 self.siblings = parent.children
556                         parent.children = self
557                 else:
558                         self.parent = self
559
560         def dumpme(self, lvl):
561                 print "%d: type %s" % (lvl, self.type)
562                 print "%d: instance %d" % (lvl, self.instance)
563                 print "%d: dir %s" % (lvl,self.dir)
564                 print "%d: flatten_name %s" % (lvl,self.flatten_name)
565                 print "%d: parent %s" % (lvl,self.parent.type)
566                 print "%d: parent dir %s" % (lvl,self.parent.dir)
567                 if (self.children):
568                         print "%d: child %s" % (lvl, self.children.dir)
569                 if (self.siblings):
570                         print "%d: siblings %s" % (lvl, self.siblings.dir)
571                 print "%d: initcode " % lvl
572                 for i in self.initcode:
573                         print "  %s" % i
574                 print "%d: registercode " % lvl
575                 for i in self.registercode:
576                         print "  %s" % i
577                 print "\n"
578
579         def gencode(self, file):
580                 if (self.chipconfig):
581                         debug.info(debug.gencode, "gencode: chipconfig(%d)" % self.instance)
582                         file.write("#include \"%s/chip.h\"\n" % self.dir)
583                         file.write("extern struct superio_control %s_control;\n" % \
584                                         self.flatten_name)
585                         file.write("struct %s_config %s_config_%d" % (\
586                                         self.flatten_name ,\
587                                         self.flatten_name , \
588                                         self.instance))
589                         if (self.registercode):
590                                 file.write("\t= {\n")
591                                 for i in self.registercode:
592                                         file.write( "\t  %s" % i)
593                                 file.write("\t}\n")
594                         else:
595                                 file.write(";")
596                         file.write("\n");
597                 if (self.instance):
598                         file.write("struct chip dev%d = {\n" % self.instance)
599                 else:
600                         file.write("struct chip root = {\n")
601                 file.write("/* %s %s */\n" % (self.type, self.dir))
602                 #file.write("  .devfn = %d,\n" % self.devfn)
603                 if (self.siblings):
604                         debug.info(debug.gencode, "gencode: siblings(%d)" % self.siblings.instance)
605                         file.write("  .next = &dev%d,\n" % self.siblings.instance)
606                 if (self.children):
607                         debug.info(debug.gencode, "gencode: children(%d)" % self.children.instance)
608                         file.write("  .children = &dev%d,\n" % \
609                                         self.children.instance)
610                 if (self.private):
611                         file.write("  .private = private%d,\n" % self.instance)
612                 if (self.chipconfig):
613                         # set the pointer to the structure for all this
614                         # type of part
615                         file.write("  .control= &%s_control,\n" % \
616                                         self.flatten_name )
617                         # generate the pointer to the isntance
618                         # of the chip struct
619                         file.write("  .chip_config = (void *) &%s_config_%d,\n" %\
620                                         (self.flatten_name, self.instance ))
621                 file.write("};\n")
622                 
623         def irq(self, irq):
624                 self.irq = irq
625        
626         def addinit(self, code):
627                 self.initcode.append(code)
628                 
629         def addregister(self, code):
630                 code = dequote(code)
631                 self.registercode.append(code)
632
633         def usesoption(self, name):
634                 global global_options
635                 o = getdict(global_options, name)
636                 if (o == 0):
637                         fatal("Error: can't use undefined option %s" % name)
638                 o.setused()
639                 o1 = getdict(self.uses_options, name)
640                 if (o1):
641                         return
642                 setdict(self.uses_options, name, o)
643
644 # -----------------------------------------------------------------------------
645 #                    statements 
646 # -----------------------------------------------------------------------------
647
648 def getdict(dict, name):
649         if name not in dict.keys(): 
650                 debug.info(debug.dict, "Undefined: %s" % name)
651                 return 0
652         v = dict.get(name, 0)
653         debug.info(debug.dict, "getdict %s returning %s" % (name, v))
654         return v
655
656 def setdict(dict, name, value):
657         debug.info(debug.dict, "setdict sets %s to %s" % (name, value))
658         dict[name] = value
659
660 # options. 
661 # to create an option, it has to not exist. 
662 # When an option value is fetched, the fact that it was used is 
663 # remembered. 
664 # Legal things to do:
665 # set a default value, then set a real value before the option is used.
666 # set a value, try to set a default, default silently fails.
667 # Illegal:
668 # use the value, then try to set the value
669
670 def newoption(name):
671         global global_options, global_options_by_order
672         o = getdict(global_options, name)
673         if (o):
674                 print "option %s already defined" % name
675                 sys.exit(1)
676         o = option(name)
677         setdict(global_options, name, o)
678         global_options_by_order.append(name)
679
680 def getoption(name, image):
681         """option must be declared before being used in a part
682         if we're not processing a part, then we must
683         be at the top level where all options are available
684         global global_uses_options, global_option_values"""
685         curpart = partstack.tos()
686         if (curpart):
687                 o = getdict(curpart.uses_options, name)
688         elif (alloptions):
689                 o = getdict(global_options, name)
690         else:
691                 o = getdict(global_uses_options, name)
692         if (o == 0 or not o.defined):
693                 error("Option %s undefined (missing use command?)" % name)
694                 return
695         v = 0
696         if (image):
697                 v = o.getvalue(image, image.getvalues())
698         if (v == 0):
699                 v = o.getvalue(image, global_option_values)
700         return v.contents()
701
702 def setoption(name, value):
703         global loc, global_options, global_option_values, curimage
704         curpart = partstack.tos()
705         if (curpart and curpart.type != 'mainboard'):
706                 fatal("Options may only be set in top-level and mainboard configuration files")
707         o = getdict(global_options, name)
708         if (o == 0):
709                 fatal("Attempt to set nonexistent option %s" % name)
710         v = option_value(value)
711         if (curimage):
712                 o.setvalue(v, curimage.getvalues(), loc)
713         else:
714                 o.setvalue(v, global_option_values, loc)
715
716 def setdefault(name, value):
717         global loc, global_options
718         o = getdict(global_options, name)
719         if (not o):
720                 return
721         if (o.default):
722                 print "setdefault: attempt to duplicate default for %s" % name
723                 return
724         v = option_value(value)
725         o.setdefault(v, loc)
726
727 def setnodefault(name):
728         global loc, global_options
729         o = getdict(global_options, name)
730         if (not o):
731                 return
732         if (o.default):
733                 print "setdefault: attempt to duplicate default for %s" % name
734                 return
735         o.setnodefault(loc)
736
737 def setcomment(name, value):
738         global loc, global_options
739         o = getdict(global_options, name)
740         if (not o):
741                 fatal("setcomment: %s not here" % name)
742         o.setcomment(value, loc)
743
744 def setexported(name):
745         global global_options
746         o = getdict(global_options, name)
747         if (not o):
748                 fatal("setexported: %s not here" % name)
749         o.setexported()
750
751 def setnoexport(name):
752         global global_options
753         o = getdict(global_options, name)
754         if (not o):
755                 fatal("setnoexport: %s not here" % name)
756         o.setnoexport()
757
758 def setexportable(name):
759         global global_options
760         o = getdict(global_options, name)
761         if (not o):
762                 fatal("setexportable: %s not here" % name)
763         o.setexportable()
764
765 def setformat(name, fmt):
766         global global_options
767         o = getdict(global_options, name)
768         if (not o):
769                 fatal("setformat: %s not here" % name)
770         o.setformat(fmt)
771
772 def getformated(name, image):
773         global global_options, global_option_values
774         o = getdict(global_options, name)
775         if (o == 0 or not o.defined):
776                 fatal( "Option %s undefined." % name)
777         v = 0
778         if (image):
779                 v = o.getvalue(image, image.getvalues())
780         if (v == 0):
781                 v = o.getvalue(image, global_option_values)
782         f = o.getformat()
783         return (f % v.contents())
784
785 def isexported(name):
786         global global_options
787         o = getdict(global_options, name)
788         if (o):
789                 return o.isexported()
790         return 0
791
792 #def isdefined(name, part):
793 #       global global_options
794 #       if (part):
795 #               o = getdict(part.uses_options, name)
796 #       else:
797 #               o = getdict(global_options, name)
798 #       if (o):
799 #               return o.isdefined()
800 #       return 0
801
802 def isset(name, part):
803         global global_uses_options
804         if (part):
805                 o = getdict(part.uses_options, name)
806         else:
807                 o = getdict(global_uses_options, name)
808         if (o):
809                 return o.isset()
810         return 0
811
812 #def isused(name, part):
813 #       global global_options
814 #       if (part):
815 #               o = getdict(part.uses_options, name)
816 #       else:
817 #               o = getdict(global_options, name)
818 #       if (o):
819 #               return o.isused()
820 #       return 0
821
822 def usesoption(name):
823         global global_options, global_uses_options
824         curpart = partstack.tos()
825         if (curpart):
826                 curpart.usesoption(name)
827                 return
828         o = getdict(global_options, name)
829         if (o == 0):
830                 fatal("Can't use undefined option %s" % name)
831         o.setused()
832         o1 = getdict(global_uses_options, name)
833         if (o1):
834                 return
835         setdict(global_uses_options, name, o)
836
837 def validdef(name, defval):
838         global global_options
839         o = getdict(global_options, name)
840         if (not o):
841                 fatal("validdef: %s not here" % name)
842         if ((defval & 1) != 1):
843             fatal("Must specify default value for option %s" % name)
844         if ((defval & 2) != 2):
845             fatal("Must specify export for option %s" % name)
846         if ((defval & 4) != 4):
847             fatal("Must specify comment for option %s" % name)
848
849 def loadoptions():
850         file = os.path.join('src', 'config', 'Options.lb')
851         optionsfile = os.path.join(treetop, file)
852         loc.push(file)
853         if (not parse('options', open(optionsfile, 'r').read())):
854                 fatal("Could not parse file")
855         loc.pop()
856
857 def addinit(path):
858         global curimage, dirstack
859         if (path[0] == '/'):
860                 curimage.setinitfile(treetop + '/src/' + path)
861         else:
862                 curimage.setinitfile(dirstack.tos() + '/' + path)
863         print "Adding init file: %s" % path
864
865 def addregister(code):
866         global partstack
867         curpart = partstack.tos()
868         curpart.addregister(code)
869
870 def addcrt0include(path):
871         """we do the crt0include as a dictionary, so that if needed we
872         can trace who added what when. Also it makes the keys
873         nice and unique."""
874         global curimage
875         curimage.addinitinclude(0, path)
876
877 def addinitinclude(str, path):
878         global curimage
879         curimage.addinitinclude(dequote(str), path)
880
881 def addldscript(path):
882         global curimage, dirstack
883         curdir = dirstack.tos()
884         if (path[0] == '/'):
885                 fullpath =  treetop + '/src/' + path
886         else:
887                 fullpath = curdir + '/' + path
888         debug.info(debug.statement, "fullpath :%s: curdir :%s: path :%s:" % (fullpath, curdir, path))
889         curimage.addldscript(fullpath)
890
891 def payload(path):
892         global curimage
893         curimage.setpayload(path)
894 #       adduserdefine("PAYLOAD:=%s"%path)
895 #       addrule('payload')
896 #       adddep('payload', path)
897 #       addaction('payload', 'cp $< $@')
898
899 def startromimage(name):
900         global romimages, curimage, target_dir, target_name
901         print "Configuring ROMIMAGE %s" % name
902         o = getdict(romimages, name)
903         if (o):
904                 fatal("romimage %s previously defined" % name)
905         curimage = romimage(name)
906         curimage.settargetdir(os.path.join(target_dir, name))
907         #o = partobj(curimage, target_dir, 0, 'board', target_name)
908         #curimage.setroot(o)
909         setdict(romimages, name, curimage)
910
911 def endromimage():
912         global curimage
913         print "End ROMIMAGE"
914         curimage = 0
915         #curpart = 0
916
917 def mainboard(path):
918         full_path = os.path.join(treetop, 'src', 'mainboard', path)
919         setoption('MAINBOARD', full_path)
920         vendor = re.sub("/.*", "", path)
921         part_number = re.sub("[^/]*/", "", path)
922         setoption('MAINBOARD_VENDOR', vendor)
923         setoption('MAINBOARD_PART_NUMBER', part_number)
924         dodir('/config', 'Config.lb')
925         part('mainboard', path, 'Config.lb')
926         curimage.setroot(partstack.tos())
927         partpop()
928
929 def addbuildrom(size, roms):
930         global buildroms
931         print "Build ROM size %d" % size
932         b = buildrom(size, roms)
933         buildroms.append(b)
934
935 def addinitobject(object_name):
936         global curimage
937         curimage.addinitobjectrule(object_name)
938
939 def addobject(object_name):
940         global curimage
941         curimage.addobjectrule(object_name)
942
943 def adddriver(driver_name):
944         global curimage
945         curimage.adddriverrule(driver_name)
946
947 def target(name):
948         global target_dir, target_name
949         print "Configuring TARGET %s" % name
950         target_name = name
951         target_dir = os.path.join(os.path.dirname(loc.file()), name)
952         if not os.path.isdir(target_dir):
953                 print "Creating directory %s" % target_dir
954                 os.makedirs(target_dir)
955         print "Will place Makefile, crt0.S, etc. in %s" % target_dir
956
957
958 def part(name, path, file):
959         global curimage, dirstack, partstack
960         partdir = os.path.join(name, path)
961         srcdir = os.path.join(treetop, 'src')
962         fulldir = os.path.join(srcdir, partdir)
963         newpart = partobj(curimage, fulldir, partstack.tos(), name, path)
964         print "Configuring PART %s, path %s" % (name, path)
965         partstack.push(newpart)
966         dirstack.push(fulldir)
967         doconfigfile(srcdir, partdir, file)
968
969 def partpop():
970         global dirstack, partstack
971         curpart = partstack.pop()
972         if (curpart == 0):
973                 fatal("Trying to pop non-existent part")
974         print "End PART %s" % curpart.type
975         # Warn if options are used without being set in this part
976         for i in curpart.uses_options.keys():
977                 if (not isset(i, curpart)):
978                         print "WARNING: Option %s using default value %s" % (i, getformated(i, curpart.image))
979         dirstack.pop()
980
981 def dodir(path, file):
982         """dodir is like part but there is no new part"""
983         global dirstack
984         # if the first char is '/', it is relative to treetop, 
985         # else relative to curdir
986         # os.path.join screws up if the name starts with '/', sigh.
987         print "Configuring DIR %s" % os.path.join(path, file)
988         if (path[0] == '/'):
989                 fullpath = os.path.join(treetop, 'src')
990                 path = re.sub('^/*', '', path)
991         else:
992                 fullpath = dirstack.tos()
993         debug.info(debug.statement, "DODIR: path %s, fullpath %s" % (path, fullpath))
994         dirstack.push(os.path.join(fullpath, path))
995         doconfigfile(fullpath, path, file)
996         dirstack.pop()
997
998 def lookup(name):
999         global curimage
1000         v = getoption(name, curimage)
1001         exitiferrors()
1002         return v
1003
1004 def addrule(id):
1005         global curimage
1006         curimage.addmakerule(id)
1007         
1008 def adduserdefine(str):
1009         global curimage
1010         curimage.adduserdefine(str)
1011
1012 def addaction(id, str):
1013         global curimage
1014         curimage.addmakeaction(id, str)
1015
1016 def adddep(id, str):
1017         global curimage
1018         curimage.addmakedepend(id, str)
1019
1020 def set_arch(my_arch):
1021         """arch is 'different' ... darn it."""
1022         global curimage
1023         curimage.setarch(my_arch)
1024         setoption('ARCH', my_arch)
1025         part('arch', my_arch, 'Config.lb')
1026
1027 def doconfigfile(path, confdir, file):
1028         rname = os.path.join(confdir, file)
1029         loc.push(rname)
1030         fullpath = os.path.join(path, rname)
1031         if (not parse('cfgfile', open(fullpath, 'r').read())):
1032                 fatal("Could not parse file")
1033         exitiferrors()
1034         loc.pop()
1035
1036 #=============================================================================
1037 #               MISC FUNCTIONS
1038 #=============================================================================
1039 def ternary(val, yes, no):
1040         debug.info(debug.statement, "ternary %s" % expr)
1041         debug.info(debug.statement, "expr %s a %d yes %d no %d"% (expr, a, yes, no))
1042         if (val == 0):
1043                 debug.info(debug.statement, "Ternary returns %d" % yes)
1044                 return yes
1045         else:
1046                 debug.info(debug.statement, "Ternary returns %d" % no)
1047                 return no
1048
1049 def tohex(name):
1050         """atoi is in the python library, but not strtol? Weird!"""
1051         return eval('int(%s)' % name)
1052
1053 def IsInt( str ):
1054         """ Is the given string an integer?"""
1055         try:
1056                 num = int(str)
1057                 return 1
1058         except ValueError:
1059                 return 0
1060
1061 def dequote(str):
1062         a = re.sub("^\"", "", str)
1063         a = re.sub("\"$", "", a)
1064         # highly un-intuitive, need four \!
1065         a = re.sub("\\\\\"", "\"", a)
1066         return a
1067
1068 def flatten_name(str):
1069         a = re.sub("/", "_", str)
1070         return a
1071
1072 def topify(path):
1073         """If the first part of <path> matches treetop, replace 
1074         that part with $(TOP)"""
1075         if path[0:len(treetop)] == treetop:
1076                 path = path[len(treetop):len(path)]
1077                 if (path[0:1] == "/"):
1078                         path = path[1:len(path)]
1079                 path = "$(TOP)/" + path
1080         return path
1081
1082 %%
1083 # to make if work without 2 passses, we use an old hack from SIMD, the 
1084 # context bit. If the bit is 1, then ops get done, otherwise
1085 # ops don't get done. From the top level, context is always
1086 # 1. In an if, context depends on eval of the if condition
1087
1088 parser Config:
1089     ignore:                     r'\s+'
1090     ignore:                     "#.*?\r?\n"
1091
1092     # less general tokens should come first, otherwise they get matched
1093     # by the re's
1094     token ACTION:               'action'
1095     token ADDACTION:            'addaction'
1096     token ALWAYS:               'always'
1097     token ARCH:                 'arch'
1098     token BUILDROM:             'buildrom'
1099     token COMMENT:              'comment'
1100     token CPU:                  'cpu'
1101     token DEFAULT:              'default'
1102     token DEFINE:               'define'
1103     token DEPENDS:              'depends'
1104     token DIR:                  'dir'
1105     token DRIVER:               'driver'
1106     token ELSE:                 'else'
1107     token END:                  'end'
1108     token EOF:                  '$'
1109     token EQ:                   '='
1110     token EXPORT:               'export'
1111     token FORMAT:               'format'
1112     token IF:                   'if'
1113     token INIT:                 'init'
1114     token INITOBJECT:           'initobject'
1115     token INITINCLUDE:          'initinclude'
1116     token LDSCRIPT:             'ldscript'
1117     token LOADOPTIONS:          'loadoptions'
1118     token MAINBOARD:            'mainboard'
1119     token MAINBOARDINIT:        'mainboardinit'
1120     token MAKEDEFINE:           'makedefine'
1121     token MAKERULE:             'makerule'
1122     token NEVER:                'never'
1123     token NONE:                 'none'
1124     token NORTHBRIDGE:          'northbridge'
1125     token OBJECT:               'object'
1126     token OPTION:               'option'
1127     token PAYLOAD:              'payload'
1128     token PMC:                  'pmc'
1129     token PRINT:                'print'
1130     token REGISTER:             'register'
1131     token ROMIMAGE:             'romimage'
1132     token SOUTHBRIDGE:          'southbridge'
1133     token SUPERIO:              'superio'
1134     token TARGET:               'target'
1135     token USED:                 'used'
1136     token USES:                 'uses'
1137     token NUM:                  r'[0-9]+'
1138     token XNUM:                 r'0x[0-9a-fA-F]+'
1139     # Why is path separate? Because paths to resources have to at least
1140     # have a slash, we thinks
1141     token PATH:                 r'[a-zA-Z0-9_.][a-zA-Z0-9/_.]+[a-zA-Z0-9_.]+'
1142     # Dir's on the other hand are abitrary
1143     # this may all be stupid.
1144     token DIRPATH:              r'[-a-zA-Z0-9_$()./]+'
1145     token ID:                   r'[a-zA-Z_.]+[a-zA-Z0-9_.]*'
1146     token DELEXPR:              r'{([^}]+|\\.)*}'
1147     token STR:                  r'"([^\\"]+|\\.)*"'
1148     token RAWTEXT:              r'.*'
1149
1150     rule expr:          logical                 {{ l = logical }}
1151                         ( "&&" logical          {{ l = l and logical }}
1152                         | "||"  logical         {{ l = l or logical }}
1153                         )*                      {{ return l }}
1154
1155     rule logical:       factor                  {{ n = factor }}
1156                         ( "[+]" factor          {{ n = n+factor }}
1157                         | "-"  factor           {{ n = n-factor }}
1158                         )*                      {{ return n }}
1159
1160     rule factor:        term                    {{ v = term }}
1161                         ( "[*]" term            {{ v = v*term }}
1162                         | "/"  term             {{ v = v/term }}
1163                         | "<<"  term            {{ v = v << term }}
1164                         | ">=" term             {{ v = (v < term)}}
1165                         )*                      {{ return v }}
1166
1167     # A term is a number, variable, or an expression surrounded by parentheses
1168     rule term:          NUM                     {{ return atoi(NUM) }}
1169                 |       XNUM                    {{ return tohex(XNUM) }}
1170                 |       ID                      {{ return lookup(ID) }}
1171                 |       unop                    {{ return unop }}
1172                 |       "\\(" expr "\\)"        {{ return expr }}
1173
1174     rule unop:          "!" expr                {{ return not(expr) }}
1175
1176     rule partend<<C>>:  (stmt<<C>>)* END        {{ if (C): partpop()}}
1177
1178     rule northbridge<<C>>:
1179                         NORTHBRIDGE PATH        {{ if (C): part('northbridge', PATH, 'Config.lb') }}
1180                         partend<<C>>
1181
1182     rule superio<<C>>:  SUPERIO PATH            {{ if (C): part('superio', PATH, 'Config.lb') }}
1183                         partend<<C>>
1184
1185     rule cpu<<C>>:      CPU ID                  {{ if (C): part('cpu', ID, 'Config.lb') }}
1186                         partend<<C>>
1187
1188     rule pmc<<C>>:      PMC PATH                {{ if (C): part('pmc', PATH, 'Config.lb') }}
1189                         partend<<C>>
1190
1191     rule arch<<C>>:     ARCH ID                 {{ if (C): set_arch(ID) }}
1192                         partend<<C>>
1193
1194     rule southbridge<<C>>:
1195                         SOUTHBRIDGE PATH        {{ if (C): part('southbridge', PATH, 'Config.lb')}}
1196                         partend<<C>>
1197
1198     rule mainboardinit<<C>>:
1199                         MAINBOARDINIT DIRPATH   {{ if (C): addcrt0include(DIRPATH)}}
1200
1201     rule initinclude<<C>>: 
1202                         INITINCLUDE 
1203                         STR 
1204                         DIRPATH                 {{ if (C): addinitinclude(STR, DIRPATH)}}
1205
1206     rule initobject<<C>>:
1207                         INITOBJECT DIRPATH      {{ if (C): addinitobject(DIRPATH)}}
1208
1209     rule object<<C>>:   OBJECT DIRPATH          {{ if (C): addobject(DIRPATH)}}
1210
1211     rule driver<<C>>:   DRIVER DIRPATH          {{ if (C): adddriver(DIRPATH)}}
1212
1213     rule dir<<C>>:      DIR DIRPATH             {{ if (C): dodir(DIRPATH, 'Config.lb') }}
1214
1215     rule ldscript<<C>>: LDSCRIPT DIRPATH        {{ if (C): addldscript(DIRPATH) }}
1216
1217     rule iif<<C>>:      IF ID                   {{ c = lookup(ID) }}
1218                         (stmt<<C and c>>)* 
1219                         [ ELSE (stmt<<C and not c>>)* ]
1220                         END
1221
1222     rule depsacts<<ID, C>>:
1223                         ( DEPENDS STR           {{ if (C): adddep(ID, STR) }}
1224                         | ACTION STR            {{ if (C): addaction(ID, STR) }}
1225                         )*
1226
1227     rule makerule<<C>>: MAKERULE DIRPATH        {{ if (C): addrule(DIRPATH) }} 
1228                         depsacts<<DIRPATH, C>> 
1229                         END
1230
1231     rule makedefine<<C>>:
1232                         MAKEDEFINE RAWTEXT      {{ if (C): adduserdefine(RAWTEXT) }}
1233
1234     rule addaction<<C>>:
1235                         ADDACTION ID STR        {{ if (C): addaction(ID, STR) }}
1236
1237     rule init<<C>>:     INIT DIRPATH            {{ if (C): addinit(DIRPATH) }}
1238
1239     rule register<<C>>: REGISTER STR            {{ if (C): addregister(STR) }}
1240
1241     rule prtval:        expr                    {{ return str(expr) }}
1242                 |       STR                     {{ return STR }}
1243
1244     rule prtlist:       prtval                  {{ el = "%(" + prtval }}
1245                         ( "," prtval            {{ el = el + "," + prtval }}
1246                         )*                      {{ return el + ")" }}   
1247
1248     rule prtstmt<<C>>:  PRINT STR               {{ val = STR }}
1249                         [ "," prtlist           {{ val = val + prtlist }}
1250                         ]                       {{ if (C): print eval(val) }}
1251
1252     rule stmt<<C>>:     arch<<C>>               {{ return arch}}
1253                 |       addaction<<C>>          {{ return addaction }}
1254                 |       cpu<<C>>                {{ return cpu}}
1255                 |       dir<<C>>                {{ return dir}}
1256                 |       driver<<C>>             {{ return driver }}
1257                 |       iif<<C>>                {{ return iif }}
1258                 |       init<<C>>               {{ return init }}
1259                 |       initinclude<<C>>        {{ return initinclude }}
1260                 |       initobject<<C>>         {{ return initobject }}
1261                 |       ldscript<<C>>           {{ return ldscript}}
1262                 |       mainboardinit<<C>>      {{ return mainboardinit }}
1263                 |       makedefine<<C>>         {{ return makedefine }}
1264                 |       makerule<<C>>           {{ return makerule }}
1265                 |       northbridge<<C>>        {{ return northbridge }}
1266                 |       object<<C>>             {{ return object }}
1267                 |       option<<C>>             {{ return option }}
1268                 |       pmc<<C>>                {{ return pmc}}
1269                 |       prtstmt<<C>>            {{ return prtstmt}}
1270                 |       register<<C>>           {{ return register}}
1271                 |       southbridge<<C>>        {{ return southbridge }}
1272                 |       superio<<C>>            {{ return superio }}
1273
1274     # ENTRY for parsing Config.lb file
1275     rule cfgfile:       (uses<<1>>)* 
1276                         (stmt<<1>>)*
1277                         EOF                     {{ return 1 }}
1278
1279     rule usesid<<C>>:   ID                      {{ if (C): usesoption(ID) }}
1280
1281     rule uses<<C>>:     USES (usesid<<C>>)+
1282
1283     rule value:         STR                     {{ return dequote(STR) }} 
1284                 |       expr                    {{ return expr }}
1285                 |       DELEXPR                 {{ return DELEXPR }}
1286
1287     rule option<<C>>:   OPTION ID EQ value      {{ if (C): setoption(ID, value) }}
1288
1289     rule opif<<C>>:     IF ID                   {{ c = lookup(ID) }}
1290                         (opstmt<<C and c>>)* 
1291                         [ ELSE (opstmt<<C and not c>>)* ] 
1292                         END
1293
1294     rule opstmt<<C>>:   option<<C>>
1295                 |       opif<<C>>
1296                 |       prtstmt<<C>>
1297
1298     rule payload<<C>>:  PAYLOAD DIRPATH         {{ if (C): payload(DIRPATH) }}
1299
1300     rule mainboard<<C>>:
1301                         MAINBOARD PATH          {{ if (C): mainboard(PATH) }}
1302
1303     rule romif<<C>>:    IF ID                   {{ c = lookup(ID) }}
1304                         (romstmt<<C and c>>)* 
1305                         [ ELSE (romstmt<<C and not c>>)* ]
1306                         END
1307
1308     rule romstmt<<C>>:  romif<<C>>
1309                 |       option<<C>>
1310                 |       mainboard<<C>>
1311                 |       payload<<C>>
1312
1313     rule romimage:      ROMIMAGE STR            {{ startromimage(dequote(STR)) }}
1314                         (romstmt<<1>>)*
1315                         END                     {{ endromimage() }}
1316
1317     rule roms:          STR                     {{ s = '(' + STR }}
1318                         ( STR                   {{ s = s + "," + STR }}
1319                         )*                      {{ return eval(s + ')') }}
1320
1321     rule buildrom:      BUILDROM expr roms      {{ addbuildrom(expr, roms) }}
1322
1323     rule romstmts:      romimage 
1324                 |       buildrom
1325                 |       opstmt<<1>>
1326
1327     # ENTRY for parsing root part
1328     rule board:         LOADOPTIONS             {{ loadoptions() }}
1329                         TARGET DIRPATH          {{ target(DIRPATH) }}
1330                         (uses<<1>>)*
1331                         (romstmts)*             
1332                         EOF                     {{ return 1 }}
1333
1334     # ENTRY for parsing a delayed value
1335     rule delexpr:       "{" expr "}" EOF        {{ return expr }}
1336
1337     rule defstmts<<ID>>:                        {{ d = 0 }}
1338                         ( DEFAULT
1339                           ( value               {{ setdefault(ID, value) }}
1340                           | NONE                {{ setnodefault(ID) }}
1341                           )                     {{ d = d | 1 }}
1342                         | FORMAT STR            {{ setformat(ID, dequote(STR)) }}
1343                         | EXPORT 
1344                           ( ALWAYS              {{ setexported(ID) }}
1345                           | USED                {{ setexportable(ID) }}
1346                           | NEVER               {{ setnoexport(ID) }}
1347                           )                     {{ d = d | 2 }}
1348                         | COMMENT STR           {{ setcomment(ID, dequote(STR)); d = d | 4 }}
1349                         )+                      {{ return d }}
1350                 
1351     rule define:        DEFINE ID               {{ newoption(ID) }}
1352                         defstmts<<ID>> END      {{ validdef(ID, defstmts) }}
1353
1354     # ENTRY for parsing Options.lb file
1355     rule options:       (define)* EOF           {{ return 1 }}
1356 %%
1357
1358 #=============================================================================
1359 #               FILE OUTPUT 
1360 #=============================================================================
1361 def writemakefileheader(file, fname):
1362         file.write("# File: %s\n" % fname)
1363         file.write("# This file was generated by '%s %s %s'\n\n"
1364                 % (sys.argv[0], sys.argv[1], sys.argv[2]))
1365
1366 def writemakefilesettings(path):
1367         global treetop, target_dir
1368         # Write Makefile.settings to seperate the settings
1369         # from the actual makefile creation
1370         # In practice you need to rerun NLBConfig.py to change
1371         # these but in theory you shouldn't need to.
1372
1373         filename = os.path.join(path, "Makefile.settings")
1374         print "Creating", filename
1375         file = open(filename, 'w+')
1376         writemakefileheader(file, filename)
1377         file.write("TOP:=%s\n" % (treetop))
1378         file.write("TARGET_DIR:=%s\n" % target_dir)
1379 #       for i in global_options_by_order:
1380 #               if (isexported(i, 0)):
1381 #                       file.write("export %s:=%s\n" % (i, getformated(i, 0)))
1382 #       file.write("export VARIABLES := ")
1383 #       for i in global_options.keys():
1384 #               if (isexported(i, 0)):
1385 #                       file.write("%s " % i)
1386         file.write("\n")
1387         file.close()
1388
1389 def writeimagesettings(image):
1390         global treetop
1391         global global_options_by_order
1392         # Write Makefile.settings to seperate the settings
1393         # from the actual makefile creation
1394         # In practice you need to rerun NLBConfig.py to change
1395         # these but in theory you shouldn't need to.
1396
1397         filename = os.path.join(image.gettargetdir(), "Makefile.settings")
1398         print "Creating", filename
1399         file = open(filename, 'w+')
1400         writemakefileheader(file, filename)
1401         file.write("TOP:=%s\n" % (treetop))
1402         file.write("TARGET_DIR:=%s\n" % (image.gettargetdir()))
1403         for i in global_options_by_order:
1404                 if (isexported(i)):
1405                         file.write("export %s:=%s\n" % (i, getformated(i, image)))
1406         file.write("export VARIABLES := ")
1407         for i in global_options_by_order:
1408                 if (isexported(i)):
1409                         file.write("%s " % i)
1410         file.write("\n")
1411         file.close()
1412
1413 # write the romimage makefile
1414 # let's try the Makefile
1415 # first, dump all the -D stuff
1416
1417 def writeimagemakefile(image):
1418         makefilepath = os.path.join(image.gettargetdir(), "Makefile")
1419         print "Creating", makefilepath
1420         file = open(makefilepath, 'w+')
1421         writemakefileheader(file, makefilepath)
1422
1423         #file.write("include cpuflags\n")
1424         # Putting "include cpuflags" in the Makefile has the problem that the
1425         # cpuflags file would be generated _after_ we want to include it.
1426         # Instead, let make do the work of computing CPUFLAGS:
1427         file.write("# Get the value of TOP, VARIABLES, and several other variables.\n")
1428         file.write("include Makefile.settings\n\n")
1429         file.write("# Function to create an item like -Di586 or -DMAX_CPUS='1' or -Ui686\n")
1430         file.write("D_item = $(if $(subst undefined,,$(origin $1)),-D$1$(if $($1),='$($1)',),-U$1)\n\n")
1431         file.write("# Compute the value of CPUFLAGS here during make's first pass.\n")
1432         file.write("CPUFLAGS := $(foreach _var_,$(VARIABLES),$(call D_item,$(_var_)))\n\n")
1433
1434         for i in image.getuserdefines():
1435                 file.write("%s\n" %i)
1436         file.write("\n")
1437
1438         # main rule
1439         file.write("all: linuxbios.rom")
1440         # print out all the object dependencies
1441         file.write("\n# object dependencies (objectrules:)\n")
1442         file.write("INIT-OBJECTS :=\n")
1443         file.write("OBJECTS :=\n")
1444         file.write("DRIVER :=\n")
1445         file.write("\nSOURCES :=\n")
1446         for irule, init in image.getinitobjectrules().items():
1447                 i_name = init[0]
1448                 i_source = init[1]
1449                 file.write("INIT-OBJECTS += %s\n" % (i_name))
1450                 file.write("SOURCES += %s\n" % (i_source))
1451
1452         for objrule, obj in image.getobjectrules().items():
1453                 obj_name = obj[0]
1454                 obj_source = obj[1]
1455                 file.write("OBJECTS += %s\n" % (obj_name))
1456                 file.write("SOURCES += %s\n" % (obj_source))
1457
1458         # for chip_target.c
1459         file.write("OBJECTS += chip_%s.o\n" % target_name)
1460         file.write("SOURCES += chip_%s.c\n" % target_name)
1461
1462         for driverrule, driver in image.getdriverrules().items():
1463                 obj_name = driver[0]
1464                 obj_source = driver[1]
1465                 file.write("DRIVER += %s\n" % (obj_name))
1466                 file.write("SOURCES += %s\n" % (obj_source))
1467
1468         # Print out all ldscript.ld dependencies.
1469         file.write("\n# ldscript.ld dependencies:\n")
1470         file.write("LDSUBSCRIPTS-1 := \n" )
1471         for script in image.getldscripts():
1472                 file.write("LDSUBSCRIPTS-1 += %s\n" % topify(script))
1473
1474         # Print out the dependencies for crt0_includes.h
1475         file.write("\n# Dependencies for crt0_includes.h\n")
1476         file.write("CRT0_INCLUDES:=\n")
1477         for inc in image.getinitincludes().keys():
1478                 if (local_path.match(inc)):
1479                         file.write("CRT0_INCLUDES += %s\n" % inc)
1480                 else:
1481                         file.write("CRT0_INCLUDES += $(TOP)/src/%s\n" % inc)
1482
1483         # Print out the user defines.
1484         file.write("\n# userdefines:\n")
1485         #for udef in image.userdefines:
1486                 #file.write("%s\n" % udef)
1487                 
1488         # Print out the base rules.
1489         # Need to have a rule that counts on 'all'.
1490         file.write("\n# mainrulelist:")
1491         #file.write("\nmainrule: %s\n" % image.mainrulelist)
1492
1493         # Print out any user rules.
1494         file.write("\n# From makerule or docipl commands:\n")
1495         # Old way (hash order): for target in makebaserules.keys():
1496         # New way (config file order):
1497         #for target in image.makerule_targets:
1498                 #image.makebaserules[target].write(file)
1499
1500         file.write("\n# objectrules:\n")
1501         for objrule, obj in image.getobjectrules().items():
1502                 source = topify(obj[1])
1503                 file.write("%s: %s\n" % (obj[0], source))
1504                 file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1505                 #file.write("%s\n" % objrule[2])
1506
1507         for driverrule, driver in image.getdriverrules().items():
1508                 source = topify(driver[1])
1509                 file.write("%s: %s\n" % (driver[0], source))
1510                 file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1511                 #file.write("%s\n" % objrule[2])
1512
1513         # special rule for chips_target.c
1514         file.write("chip_%s.o: chip_%s.c\n" % (target_name, target_name))
1515         file.write("\t$(CC) -c $(CFLAGS) -o $@ $<\n")
1516
1517         # Print out the rules that will make cause the files
1518         # generated by NLBConfig.py to be remade if any dependencies change.
1519
1520         file.write("\n# Remember the automatically generated files\n")
1521         file.write("GENERATED:=\n")
1522         for genfile in ['Makefile',
1523                         'nsuperio.c',
1524                         'chip_%s.c' % target_name, 
1525                         'LinuxBIOSDoc.config' ]:
1526                 file.write("GENERATED += %s\n" % genfile)
1527         file.write("GENERATED += %s\n" % image.getincludefilename())
1528
1529         #file.write("\n# Remake Makefile (and the other files generated by\n")
1530         #file.write("# NLBConfig.py) if any config dependencies change.\n")
1531
1532         #for cfile in image.config_file_list:
1533         #       file.write("$(GENERATED): %s\n" % topify(cfile))
1534
1535         #for depfile in [ '%s' % top_config_file,    # This a duplicate, remove?
1536         #               '$(TOP)/util/config/NLBConfig.py',
1537         #               '$(TOP)/src/arch/$(ARCH)/config/make.base' ]:
1538         #       file.write("$(GENERATED): %s\n" % depfile)
1539
1540         #file.write("$(GENERATED):\n")
1541         #file.write("\tpython $(TOP)/util/config/NLBConfig.py %s $(TOP)\n"
1542         #               % top_config_file)
1543
1544         keys = image.getroot().uses_options.keys()
1545         keys.sort()
1546         file.write("\necho:\n")
1547         for key in keys:
1548                  file.write("\t@echo %s='$(%s)'\n"% (key,key))
1549
1550         for i, m in image.getmakerules().items():
1551                 file.write("%s: " %i)
1552                 for i in m.dependency:
1553                         file.write("%s " % i)
1554                 file.write("\n")
1555                 for i in m.actions:
1556                         file.write("\t%s\n" % i)
1557         file.close()
1558
1559 #
1560 def writemakefile(path):
1561         makefilepath = os.path.join(path, "Makefile")
1562         print "Creating", makefilepath
1563         file = open(makefilepath, 'w+')
1564         writemakefileheader(file, makefilepath)
1565
1566         # main rule
1567         file.write("all: ")
1568         for i in romimages.keys():
1569                 file.write("%s-rom " % i)
1570         file.write("\n\n")
1571         for i, o in romimages.items():
1572                 file.write("%s-rom:\n" % o.getname())
1573                 file.write("\tif (cd %s; \\\n" % o.getname())
1574                 file.write("\t\tmake linuxbios.rom)\\\n");
1575                 file.write("\tthen true; else exit 1; fi;\n\n")
1576         file.close()
1577
1578 def writeinitincludes(image):
1579         global include_pattern
1580         filepath = os.path.join(image.gettargetdir(), image.getincludefilename())
1581         print "Creating", filepath
1582         outfile = open(filepath, 'w+')
1583         if (image.newformat()):
1584                 infile = open(image.getinitfile(), 'r')
1585
1586                 line = infile.readline()
1587                 while (line):
1588                         p = include_pattern.match(line)
1589                         if (p):
1590                                 for i, inc in image.getinitincludes().items():
1591                                         if (inc.getstring() == p.group(1)):
1592                                                 outfile.write("#include \"%s\"\n" % inc.getpath())
1593                         else:
1594                                 outfile.write(line);
1595                         line = infile.readline()
1596
1597                 infile.close()
1598         else:
1599                 for i in image.getinitincludes().keys():
1600                         outfile.write("#include <%s>\n" % i)
1601         outfile.close()
1602
1603 def writeldoptions(image):
1604         # Write Makefile.settings to seperate the settings
1605         # from the actual makefile creation
1606         # In practice you need to rerun NLBConfig.py to change
1607         # these but in theory you shouldn't need to.
1608
1609         filename = os.path.join(image.gettargetdir(), "ldoptions")
1610         print "Creating", filename
1611         file = open(filename, 'w+')
1612         for i in global_options.keys():
1613                 if (isexported(i) and IsInt(getoption(i, image))):
1614                         file.write("%s = %s;\n" % (i, getformated(i, image)))
1615         file.close()
1616
1617 def dumptree(part, lvl):
1618         debug.info(debug.dumptree, "DUMPTREE ME is")
1619         part.dumpme(lvl)
1620         # dump the siblings -- actually are there any? not sure
1621         # siblings are:
1622         debug.info(debug.dumptree, "DUMPTREE SIBLINGS are")
1623         kid = part.siblings
1624         while (kid):
1625                 kid.dumpme(lvl)
1626                 kid = kid.siblings
1627         # dump the kids
1628         debug.info(debug.dumptree, "DUMPTREE KIDS are")
1629         #for kid in part.children:
1630         if (part.children):
1631                 dumptree(part.children, lvl+1)
1632         debug.info(debug.dumptree, "DONE DUMPTREE")
1633
1634 def writecode(image):
1635         filename = os.path.join(img_dir, "chips_%s.c" % target_name)
1636         print "Creating", filename
1637         file = open(filename, 'w+')
1638         # gen all the forward references
1639
1640         i = 0
1641         file.write("#include <device/chip.h>\n")
1642         file.write("struct chip ")
1643         while (i <= image.numparts()):
1644                 if (i):
1645                         file.write("cdev%d "% i)
1646                 else:
1647                         file.write("root ")
1648                 i = i + 1
1649         file.write(";\n")
1650         gencode(image.getroot(), file)
1651         file.close()
1652
1653 def gencode(part, file):
1654         debug.info(debug.gencode, "GENCODE ME is")
1655         part.gencode(file)
1656         # dump the siblings -- actually are there any? not sure
1657         debug.info(debug.gencode, "GENCODE SIBLINGS are")
1658         kid = part.siblings
1659         while (kid):
1660                 kid.gencode(file)
1661                 kid = kid.siblings
1662         # now dump the children 
1663         debug.info(debug.gencode, "GENCODE KIDS are")
1664         if (part.children):
1665                 gencode(part.children, file)
1666         kid = part.siblings
1667         while (kid):
1668                 if (kid.children):
1669                         gencode(kid.children, file)
1670                 kid = kid.siblings
1671         debug.info(debug.gencode, "DONE GENCODE")
1672
1673 def verifyparse(image):
1674         """Add any run-time checks to verify that parsing the configuration
1675         was successful"""
1676         if (image.newformat() and image.getinitfile() == ''):
1677                 fatal("An init file must be specified")
1678
1679 #=============================================================================
1680 #               MAIN PROGRAM
1681 #=============================================================================
1682 if __name__=='__main__':
1683         from sys import argv
1684         if (len(argv) < 3):
1685                 print 'Args: <file> <path to linuxbios>'
1686                 sys.exit(1)
1687
1688         top_config_file = os.path.abspath(sys.argv[1])
1689
1690         treetop = os.path.abspath(sys.argv[2])
1691
1692         # Now read in the customizing script...
1693         loc.push(argv[1])
1694         if (not parse('board', open(argv[1], 'r').read())):
1695                 fatal("Could not parse file")
1696         loc.pop()
1697
1698         for r in romimages.keys():
1699                 verifyparse(getdict(romimages, r))
1700
1701         # no longer need to check if an options has been used
1702         alloptions = 1
1703
1704         for image_name, image in romimages.items():
1705                 if (debug.level(debug.dumptree)):
1706                         debug.info(debug.dumptree, "DEVICE TREE:")
1707                         dumptree(image.getroot(), 0)
1708
1709                 img_dir = image.gettargetdir()
1710                 if not os.path.isdir(img_dir):
1711                         print "Creating directory %s" % img_dir
1712                         os.makedirs(img_dir)
1713
1714                 # crt0 includes
1715                 if (debug.level(debug.dump)):
1716                         for i in image.getinitincludes().keys():
1717                                 debug.info(debug.dump, "crt0include file %s" % i)
1718                         for i in image.getdriverrules().keys():
1719                                 debug.info(debug.dump, "driver file %s" % i)
1720                         for i in image.getldscripts():
1721                                 debug.info(debug.dump, "ldscript file %s" % i)
1722                         for i, m in image.getmakerules().items():
1723                                 debug.info(debug.dump, " makerule %s dep %s act %s" % (i, m.dependency, m.actions))
1724
1725                 writecode(image)
1726                 writeimagesettings(image)
1727                 writeinitincludes(image)
1728                 writeimagemakefile(image)
1729                 writeldoptions(image)
1730
1731         writemakefilesettings(target_dir)
1732         writemakefile(target_dir)
1733
1734         sys.exit(0)