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