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