blob: 1d507802c9952035a4ea8420df820e0dc1cce057 [file] [log] [blame]
Vladimir Serbinenko3129f792014-10-15 21:51:47 +02001/* This is just an experiment. Full automatic porting
2 is probably not possible but a lot can be automated. */
3package main
4
5import (
6 "bytes"
7 "flag"
8 "fmt"
9 "log"
10 "os"
11 "sort"
12 "strings"
13)
14
15type PCIAddr struct {
16 Bus int
17 Dev int
18 Func int
19}
20
21type PCIDevData struct {
22 PCIAddr
23 PCIVenID uint16
24 PCIDevID uint16
25 ConfigDump []uint8
26}
27
28type PCIDevice interface {
29 Scan(ctx Context, addr PCIDevData)
30}
31
32type InteltoolData struct {
33 GPIO map[uint16]uint32
34 RCBA map[uint16]uint32
35 IGD map[uint32]uint32
36}
37
38type DMIData struct {
39 Vendor string
40 Model string
41 Version string
42 IsLaptop bool
43}
44
45type AzaliaCodec struct {
46 Name string
47 VendorID uint32
48 SubsystemID uint32
49 CodecNo int
50 PinConfig map[int]uint32
51}
52
53type DevReader interface {
54 GetPCIList() []PCIDevData
55 GetDMI() DMIData
56 GetInteltool() InteltoolData
57 GetAzaliaCodecs() []AzaliaCodec
58 GetACPI() map[string][]byte
59 GetCPUModel() []uint32
60 GetEC() []byte
61 GetIOPorts() []IOPorts
Vladimir Serbinenko91195c62015-05-29 23:53:37 +020062 HasPS2() bool
Vladimir Serbinenko3129f792014-10-15 21:51:47 +020063}
64
65type IOPorts struct {
66 Start uint16
67 End uint16
68 Usage string
69}
70
71type SouthBridger interface {
72 GetGPIOHeader() string
73 EncodeGPE(int) int
74 DecodeGPE(int) int
75 EnableGPE(int)
76 NeedRouteGPIOManually()
77}
78
79var SouthBridge SouthBridger
80var ROMStageFiles map[string]string = map[string]string{}
81var RAMStageFiles map[string]string = map[string]string{}
82var SMMFiles map[string]string = map[string]string{}
83var MainboardInit string
84var MainboardEnable string
85var MainboardIncludes []string
86
87type Context struct {
88 MoboID string
89 KconfigName string
90 Vendor string
91 Model string
92 BaseDirectory string
93 InfoSource DevReader
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +020094 SaneVendor string
Vladimir Serbinenko3129f792014-10-15 21:51:47 +020095}
96
97type IOAPICIRQ struct {
98 APICID int
99 IRQNO [4]int
100}
101
102var IOAPICIRQs map[PCIAddr]IOAPICIRQ = map[PCIAddr]IOAPICIRQ{}
103var KconfigBool map[string]bool = map[string]bool{}
104var KconfigComment map[string]string = map[string]string{}
105var KconfigString map[string]string = map[string]string{}
106var KconfigStringUnquoted map[string]string = map[string]string{}
107var KconfigHex map[string]uint32 = map[string]uint32{}
108var KconfigInt map[string]int = map[string]int{}
109var ROMSizeKB = 0
110var ROMProtocol = ""
111var FlashROMSupport = ""
112
113func GetLE16(inp []byte) uint16 {
114 return uint16(inp[0]) | (uint16(inp[1]) << 8)
115}
116
117func FormatHexLE16(inp []byte) string {
118 return fmt.Sprintf("0x%04x", GetLE16(inp))
119}
120
121func FormatHex32(u uint32) string {
122 return fmt.Sprintf("0x%08x", u)
123}
124
125func FormatHex8(u uint8) string {
126 return fmt.Sprintf("0x%02x", u)
127}
128
129func FormatInt32(u uint32) string {
130 return fmt.Sprintf("%d", u)
131}
132
133func FormatHexLE32(d []uint8) string {
134 u := uint32(d[0]) | (uint32(d[1]) << 8) | (uint32(d[2]) << 16) | (uint32(d[3]) << 24)
135 return FormatHex32(u)
136}
137
138func FormatBool(inp bool) string {
139 if inp {
140 return "1"
141 } else {
142 return "0"
143 }
144}
145
146func sanitize(inp string) string {
147 result := strings.ToLower(inp)
148 result = strings.Replace(result, " ", "_", -1)
149 result = strings.Replace(result, ",", "_", -1)
150 for strings.HasSuffix(result, ".") {
151 result = result[0 : len(result)-1]
152 }
153 return result
154}
155
156func AddROMStageFile(Name string, Condition string) {
157 ROMStageFiles[Name] = Condition
158}
159
160func AddRAMStageFile(Name string, Condition string) {
161 RAMStageFiles[Name] = Condition
162}
163
164func AddSMMFile(Name string, Condition string) {
165 SMMFiles[Name] = Condition
166}
167
168func IsIOPortUsedBy(ctx Context, port uint16, name string) bool {
169 for _, io := range ctx.InfoSource.GetIOPorts() {
170 if io.Start <= port && port <= io.End && io.Usage == name {
171 return true
172 }
173 }
174 return false
175}
176
177var FlagOutDir = flag.String("coreboot_dir", ".", "Resulting coreboot directory")
178
179func writeMF(mf *os.File, files map[string]string, category string) {
180 keys := []string{}
181 for file, _ := range files {
182 keys = append(keys, file)
183 }
184
185 sort.Strings(keys)
186
187 for _, file := range keys {
188 condition := files[file]
189 if condition == "" {
190 fmt.Fprintf(mf, "%s-y += %s\n", category, file)
191 } else {
192 fmt.Fprintf(mf, "%s-$(%s) += %s\n", category,
193 condition, file)
194 }
195 }
196}
197
198func Create(ctx Context, name string) *os.File {
199 li := strings.LastIndex(name, "/")
200 if li > 0 {
201 os.MkdirAll(ctx.BaseDirectory+"/"+name[0:li], 0700)
202 }
203 mf, err := os.Create(ctx.BaseDirectory + "/" + name)
204 if err != nil {
205 log.Fatal(err)
206 }
207 return mf
208}
209
Arthur Heymans59302852017-05-01 10:33:56 +0200210func Add_gpl(fp *os.File) {
211 fp.WriteString(`/*
212 * This file is part of the coreboot project.
213 *
214 * Copyright (C) 2008-2009 coresystems GmbH
215 * Copyright (C) 2014 Vladimir Serbinenko
216 *
217 * This program is free software; you can redistribute it and/or
218 * modify it under the terms of the GNU General Public License as
219 * published by the Free Software Foundation; version 2 of
220 * the License.
221 *
222 * This program is distributed in the hope that it will be useful,
223 * but WITHOUT ANY WARRANTY; without even the implied warranty of
224 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
225 * GNU General Public License for more details.
226 */
227
228`)
229}
230
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200231func RestorePCI16Simple(f *os.File, pcidev PCIDevData, addr uint16) {
232 fmt.Fprintf(f, " pci_write_config16(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x);\n",
233 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
234 pcidev.ConfigDump[addr+1],
235 pcidev.ConfigDump[addr])
236}
237
238func RestorePCI32Simple(f *os.File, pcidev PCIDevData, addr uint16) {
239 fmt.Fprintf(f, " pci_write_config32(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x%02x%02x);\n",
240 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
241 pcidev.ConfigDump[addr+3],
242 pcidev.ConfigDump[addr+2],
243 pcidev.ConfigDump[addr+1],
244 pcidev.ConfigDump[addr])
245}
246
247func RestoreRCBA32(f *os.File, inteltool InteltoolData, addr uint16) {
248 fmt.Fprintf(f, "\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr])
249}
250
251type PCISlot struct {
252 PCIAddr
253 additionalComment string
254 writeEmpty bool
255}
256
257type DevTreeNode struct {
258 Bus int
259 Dev int
260 Func int
261 Disabled bool
262 Registers map[string]string
263 IOs map[uint16]uint16
264 Children []DevTreeNode
265 PCISlots []PCISlot
266 PCIController bool
267 ChildPCIBus int
268 MissingParent string
269 SubVendor uint16
270 SubSystem uint16
271 Chip string
272 Comment string
273}
274
275var DevTree DevTreeNode
276var MissingChildren map[string][]DevTreeNode = map[string][]DevTreeNode{}
277var unmatchedPCIChips map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
278var unmatchedPCIDevices map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
279
280func Offset(dt *os.File, offset int) {
281 for i := 0; i < offset; i++ {
282 fmt.Fprintf(dt, "\t")
283 }
284}
285
286func MatchDev(dev *DevTreeNode) {
287 for idx := range dev.Children {
288 MatchDev(&dev.Children[idx])
289 }
290
291 for _, slot := range dev.PCISlots {
292 slotChip, ok := unmatchedPCIChips[slot.PCIAddr]
293
294 if !ok {
295 continue
296 }
297
298 if slot.additionalComment != "" && slotChip.Comment != "" {
299 slotChip.Comment = slot.additionalComment + " " + slotChip.Comment
300 } else {
301 slotChip.Comment = slot.additionalComment + slotChip.Comment
302 }
303
304 delete(unmatchedPCIChips, slot.PCIAddr)
305 MatchDev(&slotChip)
306 dev.Children = append(dev.Children, slotChip)
307 }
308
309 if dev.PCIController {
310 for slot, slotDev := range unmatchedPCIChips {
311 if slot.Bus == dev.ChildPCIBus {
312 delete(unmatchedPCIChips, slot)
313 MatchDev(&slotDev)
314 dev.Children = append(dev.Children, slotDev)
315 }
316 }
317 }
318
319 for _, slot := range dev.PCISlots {
320 slotDev, ok := unmatchedPCIDevices[slot.PCIAddr]
321 if !ok {
322 if slot.writeEmpty {
323 dev.Children = append(dev.Children,
324 DevTreeNode{
325 Registers: map[string]string{},
326 Chip: "pci",
327 Bus: slot.Bus,
328 Dev: slot.Dev,
329 Func: slot.Func,
330 Comment: slot.additionalComment,
331 Disabled: true,
332 },
333 )
334 }
335 continue
336 }
337
338 if slot.additionalComment != "" && slotDev.Comment != "" {
339 slotDev.Comment = slot.additionalComment + " " + slotDev.Comment
340 } else {
341 slotDev.Comment = slot.additionalComment + slotDev.Comment
342 }
343
344 MatchDev(&slotDev)
345 dev.Children = append(dev.Children, slotDev)
346 delete(unmatchedPCIDevices, slot.PCIAddr)
347 }
348
349 if dev.MissingParent != "" {
350 for _, child := range MissingChildren[dev.MissingParent] {
351 MatchDev(&child)
352 dev.Children = append(dev.Children, child)
353 }
354 delete(MissingChildren, dev.MissingParent)
355 }
356
357 if dev.PCIController {
358 for slot, slotDev := range unmatchedPCIDevices {
359 if slot.Bus == dev.ChildPCIBus {
360 MatchDev(&slotDev)
361 dev.Children = append(dev.Children, slotDev)
362 delete(unmatchedPCIDevices, slot)
363 }
364 }
365 }
366}
367
368func writeOn(dt *os.File, dev DevTreeNode) {
369 if dev.Disabled {
370 fmt.Fprintf(dt, "off")
371 } else {
372 fmt.Fprintf(dt, "on")
373 }
374}
375
376func WriteDev(dt *os.File, offset int, dev DevTreeNode) {
377 Offset(dt, offset)
378 switch dev.Chip {
379 case "cpu_cluster", "lapic", "domain", "ioapic":
380 fmt.Fprintf(dt, "device %s 0x%x ", dev.Chip, dev.Dev)
381 writeOn(dt, dev)
382 case "pci", "pnp":
383 fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func)
384 writeOn(dt, dev)
385 case "i2c":
386 fmt.Fprintf(dt, "device %s %02x ", dev.Chip, dev.Dev)
387 writeOn(dt, dev)
388 default:
389 fmt.Fprintf(dt, "chip %s", dev.Chip)
390 }
391 if dev.Comment != "" {
392 fmt.Fprintf(dt, " # %s", dev.Comment)
393 }
394 fmt.Fprintf(dt, "\n")
395 if dev.Chip == "pci" && dev.SubSystem != 0 && dev.SubVendor != 0 {
396 Offset(dt, offset+1)
397 fmt.Fprintf(dt, "subsystemid 0x%04x 0x%04x\n", dev.SubVendor, dev.SubSystem)
398 }
399
400 ioapic, ok := IOAPICIRQs[PCIAddr{Bus: dev.Bus, Dev: dev.Dev, Func: dev.Func}]
401 if dev.Chip == "pci" && ok {
402 for pin, irq := range ioapic.IRQNO {
403 if irq != 0 {
404 Offset(dt, offset+1)
405 fmt.Fprintf(dt, "ioapic_irq %d INT%c 0x%x\n", ioapic.APICID, 'A'+pin, irq)
406 }
407 }
408 }
409
410 keys := []string{}
411 for reg, _ := range dev.Registers {
412 keys = append(keys, reg)
413 }
414
415 sort.Strings(keys)
416
417 for _, reg := range keys {
418 val := dev.Registers[reg]
419 Offset(dt, offset+1)
420 fmt.Fprintf(dt, "register \"%s\" = \"%s\"\n", reg, val)
421 }
422
423 ios := []int{}
424 for reg, _ := range dev.IOs {
425 ios = append(ios, int(reg))
426 }
427
428 sort.Ints(ios)
429
430 for _, reg := range ios {
431 val := dev.IOs[uint16(reg)]
432 Offset(dt, offset+1)
433 fmt.Fprintf(dt, "io 0x%x = 0x%x\n", reg, val)
434 }
435
436 for _, child := range dev.Children {
437 WriteDev(dt, offset+1, child)
438 }
439
440 Offset(dt, offset)
441 fmt.Fprintf(dt, "end\n")
442}
443
444func PutChip(domain string, cur DevTreeNode) {
445 MissingChildren[domain] = append(MissingChildren[domain], cur)
446}
447
448func PutPCIChip(addr PCIDevData, cur DevTreeNode) {
449 unmatchedPCIChips[addr.PCIAddr] = cur
450}
451
452func PutPCIDevParent(addr PCIDevData, comment string, parent string) {
453 cur := DevTreeNode{
454 Registers: map[string]string{},
455 Chip: "pci",
456 Bus: addr.Bus,
457 Dev: addr.Dev,
458 Func: addr.Func,
459 MissingParent: parent,
460 Comment: comment,
461 }
462 if addr.ConfigDump[0xa] == 0x04 && addr.ConfigDump[0xb] == 0x06 {
463 cur.PCIController = true
464 cur.ChildPCIBus = int(addr.ConfigDump[0x19])
465
466 loopCtr := 0
467 for capPtr := addr.ConfigDump[0x34]; capPtr != 0; capPtr = addr.ConfigDump[capPtr+1] {
468 /* Avoid hangs. There are only 0x100 different possible values for capPtr.
469 If we iterate longer than that, we're in endless loop. */
470 loopCtr++
471 if loopCtr > 0x100 {
472 break
473 }
474 if addr.ConfigDump[capPtr] == 0x0d {
475 cur.SubVendor = GetLE16(addr.ConfigDump[capPtr+4 : capPtr+6])
476 cur.SubSystem = GetLE16(addr.ConfigDump[capPtr+6 : capPtr+8])
477 }
478 }
479 } else {
480 cur.SubVendor = GetLE16(addr.ConfigDump[0x2c:0x2e])
481 cur.SubSystem = GetLE16(addr.ConfigDump[0x2e:0x30])
482 }
483 unmatchedPCIDevices[addr.PCIAddr] = cur
484}
485
486func PutPCIDev(addr PCIDevData, comment string) {
487 PutPCIDevParent(addr, comment, "")
488}
489
490type GenericPCI struct {
491 Comment string
492 Bus0Subdiv string
493 MissingParent string
494}
495
496type GenericVGA struct {
497 GenericPCI
498}
499
500type DSDTInclude struct {
501 Comment string
502 File string
503}
504
505type DSDTDefine struct {
506 Key string
507 Comment string
508 Value string
509}
510
511var DSDTIncludes []DSDTInclude
512var DSDTPCI0Includes []DSDTInclude
513var DSDTDefines []DSDTDefine
514
515func (g GenericPCI) Scan(ctx Context, addr PCIDevData) {
516 PutPCIDevParent(addr, g.Comment, g.MissingParent)
517}
518
519func (g GenericVGA) Scan(ctx Context, addr PCIDevData) {
520 KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x",
521 addr.PCIVenID,
522 addr.PCIDevID)
523 KconfigString["VGA_BIOS_FILE"] = fmt.Sprintf("pci%04x,%04x.rom",
524 addr.PCIVenID,
525 addr.PCIDevID)
526 PutPCIDevParent(addr, g.Comment, g.MissingParent)
527}
528
529func makeKconfigName(ctx Context) {
530 kn := Create(ctx, "Kconfig.name")
531 defer kn.Close()
532
533 fmt.Fprintf(kn, "config %s\n\tbool \"%s\"\n", ctx.KconfigName, ctx.Model)
534}
535
536func makeComment(name string) string {
537 cmt, ok := KconfigComment[name]
538 if !ok {
539 return ""
540 }
541 return " # " + cmt
542}
543
544func makeKconfig(ctx Context) {
545 kc := Create(ctx, "Kconfig")
546 defer kc.Close()
547
548 fmt.Fprintf(kc, "if %s\n\n", ctx.KconfigName)
549
550 fmt.Fprintf(kc, "config BOARD_SPECIFIC_OPTIONS # dummy\n\tdef_bool y\n")
551 keys := []string{}
552 for name, val := range KconfigBool {
553 if val {
554 keys = append(keys, name)
555 }
556 }
557
558 sort.Strings(keys)
559
560 for _, name := range keys {
561 fmt.Fprintf(kc, "\tselect %s%s\n", name, makeComment(name))
562 }
563
564 keys = nil
565 for name, val := range KconfigBool {
566 if !val {
567 keys = append(keys, name)
568 }
569 }
570
571 sort.Strings(keys)
572
573 for _, name := range keys {
574 fmt.Fprintf(kc, `
575config %s%s
576 bool
577 default n
578`, name, makeComment(name))
579 }
580
581 keys = nil
582 for name, _ := range KconfigStringUnquoted {
583 keys = append(keys, name)
584 }
585
586 sort.Strings(keys)
587
588 for _, name := range keys {
589 fmt.Fprintf(kc, `
590config %s%s
591 string
592 default %s
593`, name, makeComment(name), KconfigStringUnquoted[name])
594 }
595
596 keys = nil
597 for name, _ := range KconfigString {
598 keys = append(keys, name)
599 }
600
601 sort.Strings(keys)
602
603 for _, name := range keys {
604 fmt.Fprintf(kc, `
605config %s%s
606 string
607 default "%s"
608`, name, makeComment(name), KconfigString[name])
609 }
610
611 keys = nil
612 for name, _ := range KconfigHex {
613 keys = append(keys, name)
614 }
615
616 sort.Strings(keys)
617
618 for _, name := range keys {
619 fmt.Fprintf(kc, `
620config %s%s
621 hex
622 default 0x%x
623`, name, makeComment(name), KconfigHex[name])
624 }
625
626 keys = nil
627 for name, _ := range KconfigInt {
628 keys = append(keys, name)
629 }
630
631 sort.Strings(keys)
632
633 for _, name := range keys {
634 fmt.Fprintf(kc, `
635config %s%s
636 int
637 default %d
638`, name, makeComment(name), KconfigInt[name])
639 }
640
641 fmt.Fprintf(kc, "endif\n")
642}
643
644const MoboDir = "/src/mainboard/"
645
646func makeVendor(ctx Context) {
647 vendor := ctx.Vendor
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200648 vendorSane := ctx.SaneVendor
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200649 vendorDir := *FlagOutDir + MoboDir + vendorSane
650 vendorUpper := strings.ToUpper(vendorSane)
651 kconfig := vendorDir + "/Kconfig"
652 if _, err := os.Stat(kconfig); os.IsNotExist(err) {
653 f, err := os.Create(kconfig)
654 if err != nil {
655 log.Fatal(err)
656 }
657 defer f.Close()
658 f.WriteString(`if VENDOR_` + vendorUpper + `
659
660choice
661 prompt "Mainboard model"
662
663source "src/mainboard/` + vendorSane + `/*/Kconfig.name"
664
665endchoice
666
667source "src/mainboard/` + vendorSane + `/*/Kconfig"
668
669config MAINBOARD_VENDOR
670 string
671 default "` + vendor + `"
672
673endif # VENDOR_` + vendorUpper + "\n")
674 }
675 kconfigName := vendorDir + "/Kconfig.name"
676 if _, err := os.Stat(kconfigName); os.IsNotExist(err) {
677 f, err := os.Create(kconfigName)
678 if err != nil {
679 log.Fatal(err)
680 }
681 defer f.Close()
682 f.WriteString(`config VENDOR_` + vendorUpper + `
683 bool "` + vendor + `"
684`)
685 }
686
687}
688
689func GuessECGPE(ctx Context) int {
690 /* FIXME:XX Use iasl -d and/or better parsing */
691 dsdt := ctx.InfoSource.GetACPI()["DSDT"]
692 idx := bytes.Index(dsdt, []byte{0x08, '_', 'G', 'P', 'E', 0x0a}) /* Name (_GPE, byte). */
693 if idx > 0 {
694 return int(dsdt[idx+6])
695 }
696 return -1
697}
698
699func GuessSPDMap(ctx Context) []uint8 {
700 dmi := ctx.InfoSource.GetDMI()
701
702 if dmi.Vendor == "LENOVO" {
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200703 return []uint8{0x50, 0x52, 0x51, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200704 }
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200705 return []uint8{0x50, 0x51, 0x52, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200706}
707
708func main() {
709 flag.Parse()
710
711 ctx := Context{}
712
713 ctx.InfoSource = MakeLogReader()
714
715 dmi := ctx.InfoSource.GetDMI()
716
717 ctx.Vendor = dmi.Vendor
718
719 if dmi.Vendor == "LENOVO" {
720 ctx.Model = dmi.Version
721 } else {
722 ctx.Model = dmi.Model
723 }
724
725 if dmi.IsLaptop {
726 KconfigBool["SYSTEM_TYPE_LAPTOP"] = true
727 }
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200728 ctx.SaneVendor = sanitize(ctx.Vendor)
729 for {
730 last := ctx.SaneVendor
731 for _, suf := range []string{"_inc", "_co", "_corp"} {
732 ctx.SaneVendor = strings.TrimSuffix(ctx.SaneVendor, suf)
733 }
734 if last == ctx.SaneVendor {
735 break
736 }
737 }
738 ctx.MoboID = ctx.SaneVendor + "/" + sanitize(ctx.Model)
739 ctx.KconfigName = "BOARD_" + strings.ToUpper(ctx.SaneVendor+"_"+sanitize(ctx.Model))
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200740 ctx.BaseDirectory = *FlagOutDir + MoboDir + ctx.MoboID
741 KconfigStringUnquoted["MAINBOARD_DIR"] = ctx.MoboID
742 KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model
743
744 os.MkdirAll(ctx.BaseDirectory, 0700)
745
746 makeVendor(ctx)
747
748 ScanRoot(ctx)
749
750 if len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 {
751 mf := Create(ctx, "Makefile.inc")
752 defer mf.Close()
753 writeMF(mf, ROMStageFiles, "romstage")
754 writeMF(mf, RAMStageFiles, "ramstage")
755 writeMF(mf, SMMFiles, "smm")
756 }
757
758 devtree := Create(ctx, "devicetree.cb")
759 defer devtree.Close()
760
761 MatchDev(&DevTree)
762 WriteDev(devtree, 0, DevTree)
763
764 if MainboardInit != "" || MainboardEnable != "" || MainboardIncludes != nil {
765 mainboard := Create(ctx, "mainboard.c")
766 defer mainboard.Close()
767 mainboard.WriteString("#include <device/device.h>\n")
768 for _, include := range MainboardIncludes {
769 mainboard.WriteString("#include <" + include + ">\n")
770 }
771 mainboard.WriteString("\n")
772 if MainboardInit != "" {
773 mainboard.WriteString(`static void mainboard_init(device_t dev)
774{
775` + MainboardInit + "}\n\n")
776 }
777 if MainboardInit != "" || MainboardEnable != "" {
778 mainboard.WriteString("static void mainboard_enable(device_t dev)\n{\n")
779 if MainboardInit != "" {
780 mainboard.WriteString("\tdev->ops->init = mainboard_init;\n\n")
781 }
782 mainboard.WriteString(MainboardEnable)
783 mainboard.WriteString("}\n\n")
784 mainboard.WriteString(`struct chip_operations mainboard_ops = {
785 .enable_dev = mainboard_enable,
786};
787`)
788 }
789 }
790
791 at := Create(ctx, "acpi_tables.c")
792 defer at.Close()
793 at.WriteString("/* dummy */\n")
794
795 bi := Create(ctx, "board_info.txt")
796 defer bi.Close()
797
798 fixme := ""
799
800 if dmi.IsLaptop {
801 bi.WriteString("Category: laptop\n")
802 } else {
803 bi.WriteString("Category: desktop\n")
804 fixme += "check category, "
805 }
806
807 missing := "ROM package, ROM socketed"
808
809 if ROMProtocol != "" {
810 fmt.Fprintf(bi, "ROM protocol: %s\n", ROMProtocol)
811 } else {
812 missing += ", ROM protocol"
813 }
814
815 if FlashROMSupport != "" {
816 fmt.Fprintf(bi, "Flashrom support: %s\n", FlashROMSupport)
817 } else {
818 missing += ", Flashrom support"
819 }
820
821 missing += ", Release year"
822
823 if fixme != "" {
824 fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing)
825 } else {
826 fmt.Fprintf(bi, "FIXME: put %s\n", missing)
827 }
828
829 rs := Create(ctx, "romstage.c")
830 defer rs.Close()
831 rs.WriteString("/* dummy file */\n")
832
833 if ROMSizeKB == 0 {
834 KconfigBool["BOARD_ROMSIZE_KB_2048"] = true
835 KconfigComment["BOARD_ROMSIZE_KB_2048"] = "FIXME: correct this"
836 } else {
837 KconfigBool[fmt.Sprintf("BOARD_ROMSIZE_KB_%d", ROMSizeKB)] = true
838 }
839
840 makeKconfig(ctx)
841 makeKconfigName(ctx)
842
843 dsdt := Create(ctx, "dsdt.asl")
844 defer dsdt.Close()
845
846 for _, define := range DSDTDefines {
847 if define.Comment != "" {
848 fmt.Fprintf(dsdt, "\t/* %s. */\n", define.Comment)
849 }
850 dsdt.WriteString("#define " + define.Key + " " + define.Value + "\n")
851 }
852
853 dsdt.WriteString(
854 `DefinitionBlock(
855 "dsdt.aml",
856 "DSDT",
857 0x03, // DSDT revision: ACPI v3.0
858 "COREv4", // OEM id
859 "COREBOOT", // OEM table id
860 0x20141018 // OEM revision
861)
862{
863 // Some generic macros
864 #include "acpi/platform.asl"
865`)
866
867 for _, x := range DSDTIncludes {
868 if x.Comment != "" {
869 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
870 }
871 fmt.Fprintf(dsdt, "\t#include <%s>\n", x.File)
872 }
873
874 dsdt.WriteString(`
875 Scope (\_SB) {
876 Device (PCI0)
877 {
878`)
879 for _, x := range DSDTPCI0Includes {
880 if x.Comment != "" {
881 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
882 }
883 fmt.Fprintf(dsdt, "\t\t#include <%s>\n", x.File)
884 }
885 dsdt.WriteString(
886 ` }
887 }
888}
889`)
890
891}