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