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