blob: 2eb15881584753f8f5ce1dfcf973dc3675971c22 [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
210func RestorePCI16Simple(f *os.File, pcidev PCIDevData, addr uint16) {
211 fmt.Fprintf(f, " pci_write_config16(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x);\n",
212 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
213 pcidev.ConfigDump[addr+1],
214 pcidev.ConfigDump[addr])
215}
216
217func RestorePCI32Simple(f *os.File, pcidev PCIDevData, addr uint16) {
218 fmt.Fprintf(f, " pci_write_config32(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x%02x%02x);\n",
219 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
220 pcidev.ConfigDump[addr+3],
221 pcidev.ConfigDump[addr+2],
222 pcidev.ConfigDump[addr+1],
223 pcidev.ConfigDump[addr])
224}
225
226func RestoreRCBA32(f *os.File, inteltool InteltoolData, addr uint16) {
227 fmt.Fprintf(f, "\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr])
228}
229
230type PCISlot struct {
231 PCIAddr
232 additionalComment string
233 writeEmpty bool
234}
235
236type DevTreeNode struct {
237 Bus int
238 Dev int
239 Func int
240 Disabled bool
241 Registers map[string]string
242 IOs map[uint16]uint16
243 Children []DevTreeNode
244 PCISlots []PCISlot
245 PCIController bool
246 ChildPCIBus int
247 MissingParent string
248 SubVendor uint16
249 SubSystem uint16
250 Chip string
251 Comment string
252}
253
254var DevTree DevTreeNode
255var MissingChildren map[string][]DevTreeNode = map[string][]DevTreeNode{}
256var unmatchedPCIChips map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
257var unmatchedPCIDevices map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
258
259func Offset(dt *os.File, offset int) {
260 for i := 0; i < offset; i++ {
261 fmt.Fprintf(dt, "\t")
262 }
263}
264
265func MatchDev(dev *DevTreeNode) {
266 for idx := range dev.Children {
267 MatchDev(&dev.Children[idx])
268 }
269
270 for _, slot := range dev.PCISlots {
271 slotChip, ok := unmatchedPCIChips[slot.PCIAddr]
272
273 if !ok {
274 continue
275 }
276
277 if slot.additionalComment != "" && slotChip.Comment != "" {
278 slotChip.Comment = slot.additionalComment + " " + slotChip.Comment
279 } else {
280 slotChip.Comment = slot.additionalComment + slotChip.Comment
281 }
282
283 delete(unmatchedPCIChips, slot.PCIAddr)
284 MatchDev(&slotChip)
285 dev.Children = append(dev.Children, slotChip)
286 }
287
288 if dev.PCIController {
289 for slot, slotDev := range unmatchedPCIChips {
290 if slot.Bus == dev.ChildPCIBus {
291 delete(unmatchedPCIChips, slot)
292 MatchDev(&slotDev)
293 dev.Children = append(dev.Children, slotDev)
294 }
295 }
296 }
297
298 for _, slot := range dev.PCISlots {
299 slotDev, ok := unmatchedPCIDevices[slot.PCIAddr]
300 if !ok {
301 if slot.writeEmpty {
302 dev.Children = append(dev.Children,
303 DevTreeNode{
304 Registers: map[string]string{},
305 Chip: "pci",
306 Bus: slot.Bus,
307 Dev: slot.Dev,
308 Func: slot.Func,
309 Comment: slot.additionalComment,
310 Disabled: true,
311 },
312 )
313 }
314 continue
315 }
316
317 if slot.additionalComment != "" && slotDev.Comment != "" {
318 slotDev.Comment = slot.additionalComment + " " + slotDev.Comment
319 } else {
320 slotDev.Comment = slot.additionalComment + slotDev.Comment
321 }
322
323 MatchDev(&slotDev)
324 dev.Children = append(dev.Children, slotDev)
325 delete(unmatchedPCIDevices, slot.PCIAddr)
326 }
327
328 if dev.MissingParent != "" {
329 for _, child := range MissingChildren[dev.MissingParent] {
330 MatchDev(&child)
331 dev.Children = append(dev.Children, child)
332 }
333 delete(MissingChildren, dev.MissingParent)
334 }
335
336 if dev.PCIController {
337 for slot, slotDev := range unmatchedPCIDevices {
338 if slot.Bus == dev.ChildPCIBus {
339 MatchDev(&slotDev)
340 dev.Children = append(dev.Children, slotDev)
341 delete(unmatchedPCIDevices, slot)
342 }
343 }
344 }
345}
346
347func writeOn(dt *os.File, dev DevTreeNode) {
348 if dev.Disabled {
349 fmt.Fprintf(dt, "off")
350 } else {
351 fmt.Fprintf(dt, "on")
352 }
353}
354
355func WriteDev(dt *os.File, offset int, dev DevTreeNode) {
356 Offset(dt, offset)
357 switch dev.Chip {
358 case "cpu_cluster", "lapic", "domain", "ioapic":
359 fmt.Fprintf(dt, "device %s 0x%x ", dev.Chip, dev.Dev)
360 writeOn(dt, dev)
361 case "pci", "pnp":
362 fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func)
363 writeOn(dt, dev)
364 case "i2c":
365 fmt.Fprintf(dt, "device %s %02x ", dev.Chip, dev.Dev)
366 writeOn(dt, dev)
367 default:
368 fmt.Fprintf(dt, "chip %s", dev.Chip)
369 }
370 if dev.Comment != "" {
371 fmt.Fprintf(dt, " # %s", dev.Comment)
372 }
373 fmt.Fprintf(dt, "\n")
374 if dev.Chip == "pci" && dev.SubSystem != 0 && dev.SubVendor != 0 {
375 Offset(dt, offset+1)
376 fmt.Fprintf(dt, "subsystemid 0x%04x 0x%04x\n", dev.SubVendor, dev.SubSystem)
377 }
378
379 ioapic, ok := IOAPICIRQs[PCIAddr{Bus: dev.Bus, Dev: dev.Dev, Func: dev.Func}]
380 if dev.Chip == "pci" && ok {
381 for pin, irq := range ioapic.IRQNO {
382 if irq != 0 {
383 Offset(dt, offset+1)
384 fmt.Fprintf(dt, "ioapic_irq %d INT%c 0x%x\n", ioapic.APICID, 'A'+pin, irq)
385 }
386 }
387 }
388
389 keys := []string{}
390 for reg, _ := range dev.Registers {
391 keys = append(keys, reg)
392 }
393
394 sort.Strings(keys)
395
396 for _, reg := range keys {
397 val := dev.Registers[reg]
398 Offset(dt, offset+1)
399 fmt.Fprintf(dt, "register \"%s\" = \"%s\"\n", reg, val)
400 }
401
402 ios := []int{}
403 for reg, _ := range dev.IOs {
404 ios = append(ios, int(reg))
405 }
406
407 sort.Ints(ios)
408
409 for _, reg := range ios {
410 val := dev.IOs[uint16(reg)]
411 Offset(dt, offset+1)
412 fmt.Fprintf(dt, "io 0x%x = 0x%x\n", reg, val)
413 }
414
415 for _, child := range dev.Children {
416 WriteDev(dt, offset+1, child)
417 }
418
419 Offset(dt, offset)
420 fmt.Fprintf(dt, "end\n")
421}
422
423func PutChip(domain string, cur DevTreeNode) {
424 MissingChildren[domain] = append(MissingChildren[domain], cur)
425}
426
427func PutPCIChip(addr PCIDevData, cur DevTreeNode) {
428 unmatchedPCIChips[addr.PCIAddr] = cur
429}
430
431func PutPCIDevParent(addr PCIDevData, comment string, parent string) {
432 cur := DevTreeNode{
433 Registers: map[string]string{},
434 Chip: "pci",
435 Bus: addr.Bus,
436 Dev: addr.Dev,
437 Func: addr.Func,
438 MissingParent: parent,
439 Comment: comment,
440 }
441 if addr.ConfigDump[0xa] == 0x04 && addr.ConfigDump[0xb] == 0x06 {
442 cur.PCIController = true
443 cur.ChildPCIBus = int(addr.ConfigDump[0x19])
444
445 loopCtr := 0
446 for capPtr := addr.ConfigDump[0x34]; capPtr != 0; capPtr = addr.ConfigDump[capPtr+1] {
447 /* Avoid hangs. There are only 0x100 different possible values for capPtr.
448 If we iterate longer than that, we're in endless loop. */
449 loopCtr++
450 if loopCtr > 0x100 {
451 break
452 }
453 if addr.ConfigDump[capPtr] == 0x0d {
454 cur.SubVendor = GetLE16(addr.ConfigDump[capPtr+4 : capPtr+6])
455 cur.SubSystem = GetLE16(addr.ConfigDump[capPtr+6 : capPtr+8])
456 }
457 }
458 } else {
459 cur.SubVendor = GetLE16(addr.ConfigDump[0x2c:0x2e])
460 cur.SubSystem = GetLE16(addr.ConfigDump[0x2e:0x30])
461 }
462 unmatchedPCIDevices[addr.PCIAddr] = cur
463}
464
465func PutPCIDev(addr PCIDevData, comment string) {
466 PutPCIDevParent(addr, comment, "")
467}
468
469type GenericPCI struct {
470 Comment string
471 Bus0Subdiv string
472 MissingParent string
473}
474
475type GenericVGA struct {
476 GenericPCI
477}
478
479type DSDTInclude struct {
480 Comment string
481 File string
482}
483
484type DSDTDefine struct {
485 Key string
486 Comment string
487 Value string
488}
489
490var DSDTIncludes []DSDTInclude
491var DSDTPCI0Includes []DSDTInclude
492var DSDTDefines []DSDTDefine
493
494func (g GenericPCI) Scan(ctx Context, addr PCIDevData) {
495 PutPCIDevParent(addr, g.Comment, g.MissingParent)
496}
497
498func (g GenericVGA) Scan(ctx Context, addr PCIDevData) {
499 KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x",
500 addr.PCIVenID,
501 addr.PCIDevID)
502 KconfigString["VGA_BIOS_FILE"] = fmt.Sprintf("pci%04x,%04x.rom",
503 addr.PCIVenID,
504 addr.PCIDevID)
505 PutPCIDevParent(addr, g.Comment, g.MissingParent)
506}
507
508func makeKconfigName(ctx Context) {
509 kn := Create(ctx, "Kconfig.name")
510 defer kn.Close()
511
512 fmt.Fprintf(kn, "config %s\n\tbool \"%s\"\n", ctx.KconfigName, ctx.Model)
513}
514
515func makeComment(name string) string {
516 cmt, ok := KconfigComment[name]
517 if !ok {
518 return ""
519 }
520 return " # " + cmt
521}
522
523func makeKconfig(ctx Context) {
524 kc := Create(ctx, "Kconfig")
525 defer kc.Close()
526
527 fmt.Fprintf(kc, "if %s\n\n", ctx.KconfigName)
528
529 fmt.Fprintf(kc, "config BOARD_SPECIFIC_OPTIONS # dummy\n\tdef_bool y\n")
530 keys := []string{}
531 for name, val := range KconfigBool {
532 if val {
533 keys = append(keys, name)
534 }
535 }
536
537 sort.Strings(keys)
538
539 for _, name := range keys {
540 fmt.Fprintf(kc, "\tselect %s%s\n", name, makeComment(name))
541 }
542
543 keys = nil
544 for name, val := range KconfigBool {
545 if !val {
546 keys = append(keys, name)
547 }
548 }
549
550 sort.Strings(keys)
551
552 for _, name := range keys {
553 fmt.Fprintf(kc, `
554config %s%s
555 bool
556 default n
557`, name, makeComment(name))
558 }
559
560 keys = nil
561 for name, _ := range KconfigStringUnquoted {
562 keys = append(keys, name)
563 }
564
565 sort.Strings(keys)
566
567 for _, name := range keys {
568 fmt.Fprintf(kc, `
569config %s%s
570 string
571 default %s
572`, name, makeComment(name), KconfigStringUnquoted[name])
573 }
574
575 keys = nil
576 for name, _ := range KconfigString {
577 keys = append(keys, name)
578 }
579
580 sort.Strings(keys)
581
582 for _, name := range keys {
583 fmt.Fprintf(kc, `
584config %s%s
585 string
586 default "%s"
587`, name, makeComment(name), KconfigString[name])
588 }
589
590 keys = nil
591 for name, _ := range KconfigHex {
592 keys = append(keys, name)
593 }
594
595 sort.Strings(keys)
596
597 for _, name := range keys {
598 fmt.Fprintf(kc, `
599config %s%s
600 hex
601 default 0x%x
602`, name, makeComment(name), KconfigHex[name])
603 }
604
605 keys = nil
606 for name, _ := range KconfigInt {
607 keys = append(keys, name)
608 }
609
610 sort.Strings(keys)
611
612 for _, name := range keys {
613 fmt.Fprintf(kc, `
614config %s%s
615 int
616 default %d
617`, name, makeComment(name), KconfigInt[name])
618 }
619
620 fmt.Fprintf(kc, "endif\n")
621}
622
623const MoboDir = "/src/mainboard/"
624
625func makeVendor(ctx Context) {
626 vendor := ctx.Vendor
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200627 vendorSane := ctx.SaneVendor
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200628 vendorDir := *FlagOutDir + MoboDir + vendorSane
629 vendorUpper := strings.ToUpper(vendorSane)
630 kconfig := vendorDir + "/Kconfig"
631 if _, err := os.Stat(kconfig); os.IsNotExist(err) {
632 f, err := os.Create(kconfig)
633 if err != nil {
634 log.Fatal(err)
635 }
636 defer f.Close()
637 f.WriteString(`if VENDOR_` + vendorUpper + `
638
639choice
640 prompt "Mainboard model"
641
642source "src/mainboard/` + vendorSane + `/*/Kconfig.name"
643
644endchoice
645
646source "src/mainboard/` + vendorSane + `/*/Kconfig"
647
648config MAINBOARD_VENDOR
649 string
650 default "` + vendor + `"
651
652endif # VENDOR_` + vendorUpper + "\n")
653 }
654 kconfigName := vendorDir + "/Kconfig.name"
655 if _, err := os.Stat(kconfigName); os.IsNotExist(err) {
656 f, err := os.Create(kconfigName)
657 if err != nil {
658 log.Fatal(err)
659 }
660 defer f.Close()
661 f.WriteString(`config VENDOR_` + vendorUpper + `
662 bool "` + vendor + `"
663`)
664 }
665
666}
667
668func GuessECGPE(ctx Context) int {
669 /* FIXME:XX Use iasl -d and/or better parsing */
670 dsdt := ctx.InfoSource.GetACPI()["DSDT"]
671 idx := bytes.Index(dsdt, []byte{0x08, '_', 'G', 'P', 'E', 0x0a}) /* Name (_GPE, byte). */
672 if idx > 0 {
673 return int(dsdt[idx+6])
674 }
675 return -1
676}
677
678func GuessSPDMap(ctx Context) []uint8 {
679 dmi := ctx.InfoSource.GetDMI()
680
681 if dmi.Vendor == "LENOVO" {
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200682 return []uint8{0x50, 0x52, 0x51, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200683 }
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200684 return []uint8{0x50, 0x51, 0x52, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200685}
686
687func main() {
688 flag.Parse()
689
690 ctx := Context{}
691
692 ctx.InfoSource = MakeLogReader()
693
694 dmi := ctx.InfoSource.GetDMI()
695
696 ctx.Vendor = dmi.Vendor
697
698 if dmi.Vendor == "LENOVO" {
699 ctx.Model = dmi.Version
700 } else {
701 ctx.Model = dmi.Model
702 }
703
704 if dmi.IsLaptop {
705 KconfigBool["SYSTEM_TYPE_LAPTOP"] = true
706 }
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200707 ctx.SaneVendor = sanitize(ctx.Vendor)
708 for {
709 last := ctx.SaneVendor
710 for _, suf := range []string{"_inc", "_co", "_corp"} {
711 ctx.SaneVendor = strings.TrimSuffix(ctx.SaneVendor, suf)
712 }
713 if last == ctx.SaneVendor {
714 break
715 }
716 }
717 ctx.MoboID = ctx.SaneVendor + "/" + sanitize(ctx.Model)
718 ctx.KconfigName = "BOARD_" + strings.ToUpper(ctx.SaneVendor+"_"+sanitize(ctx.Model))
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200719 ctx.BaseDirectory = *FlagOutDir + MoboDir + ctx.MoboID
720 KconfigStringUnquoted["MAINBOARD_DIR"] = ctx.MoboID
721 KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model
722
723 os.MkdirAll(ctx.BaseDirectory, 0700)
724
725 makeVendor(ctx)
726
727 ScanRoot(ctx)
728
729 if len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 {
730 mf := Create(ctx, "Makefile.inc")
731 defer mf.Close()
732 writeMF(mf, ROMStageFiles, "romstage")
733 writeMF(mf, RAMStageFiles, "ramstage")
734 writeMF(mf, SMMFiles, "smm")
735 }
736
737 devtree := Create(ctx, "devicetree.cb")
738 defer devtree.Close()
739
740 MatchDev(&DevTree)
741 WriteDev(devtree, 0, DevTree)
742
743 if MainboardInit != "" || MainboardEnable != "" || MainboardIncludes != nil {
744 mainboard := Create(ctx, "mainboard.c")
745 defer mainboard.Close()
746 mainboard.WriteString("#include <device/device.h>\n")
747 for _, include := range MainboardIncludes {
748 mainboard.WriteString("#include <" + include + ">\n")
749 }
750 mainboard.WriteString("\n")
751 if MainboardInit != "" {
752 mainboard.WriteString(`static void mainboard_init(device_t dev)
753{
754` + MainboardInit + "}\n\n")
755 }
756 if MainboardInit != "" || MainboardEnable != "" {
757 mainboard.WriteString("static void mainboard_enable(device_t dev)\n{\n")
758 if MainboardInit != "" {
759 mainboard.WriteString("\tdev->ops->init = mainboard_init;\n\n")
760 }
761 mainboard.WriteString(MainboardEnable)
762 mainboard.WriteString("}\n\n")
763 mainboard.WriteString(`struct chip_operations mainboard_ops = {
764 .enable_dev = mainboard_enable,
765};
766`)
767 }
768 }
769
770 at := Create(ctx, "acpi_tables.c")
771 defer at.Close()
772 at.WriteString("/* dummy */\n")
773
774 bi := Create(ctx, "board_info.txt")
775 defer bi.Close()
776
777 fixme := ""
778
779 if dmi.IsLaptop {
780 bi.WriteString("Category: laptop\n")
781 } else {
782 bi.WriteString("Category: desktop\n")
783 fixme += "check category, "
784 }
785
786 missing := "ROM package, ROM socketed"
787
788 if ROMProtocol != "" {
789 fmt.Fprintf(bi, "ROM protocol: %s\n", ROMProtocol)
790 } else {
791 missing += ", ROM protocol"
792 }
793
794 if FlashROMSupport != "" {
795 fmt.Fprintf(bi, "Flashrom support: %s\n", FlashROMSupport)
796 } else {
797 missing += ", Flashrom support"
798 }
799
800 missing += ", Release year"
801
802 if fixme != "" {
803 fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing)
804 } else {
805 fmt.Fprintf(bi, "FIXME: put %s\n", missing)
806 }
807
808 rs := Create(ctx, "romstage.c")
809 defer rs.Close()
810 rs.WriteString("/* dummy file */\n")
811
812 if ROMSizeKB == 0 {
813 KconfigBool["BOARD_ROMSIZE_KB_2048"] = true
814 KconfigComment["BOARD_ROMSIZE_KB_2048"] = "FIXME: correct this"
815 } else {
816 KconfigBool[fmt.Sprintf("BOARD_ROMSIZE_KB_%d", ROMSizeKB)] = true
817 }
818
819 makeKconfig(ctx)
820 makeKconfigName(ctx)
821
822 dsdt := Create(ctx, "dsdt.asl")
823 defer dsdt.Close()
824
825 for _, define := range DSDTDefines {
826 if define.Comment != "" {
827 fmt.Fprintf(dsdt, "\t/* %s. */\n", define.Comment)
828 }
829 dsdt.WriteString("#define " + define.Key + " " + define.Value + "\n")
830 }
831
832 dsdt.WriteString(
833 `DefinitionBlock(
834 "dsdt.aml",
835 "DSDT",
836 0x03, // DSDT revision: ACPI v3.0
837 "COREv4", // OEM id
838 "COREBOOT", // OEM table id
839 0x20141018 // OEM revision
840)
841{
842 // Some generic macros
843 #include "acpi/platform.asl"
844`)
845
846 for _, x := range DSDTIncludes {
847 if x.Comment != "" {
848 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
849 }
850 fmt.Fprintf(dsdt, "\t#include <%s>\n", x.File)
851 }
852
853 dsdt.WriteString(`
854 Scope (\_SB) {
855 Device (PCI0)
856 {
857`)
858 for _, x := range DSDTPCI0Includes {
859 if x.Comment != "" {
860 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
861 }
862 fmt.Fprintf(dsdt, "\t\t#include <%s>\n", x.File)
863 }
864 dsdt.WriteString(
865 ` }
866 }
867}
868`)
869
870}