blob: 9e62b565da37692aff25ffa19b31ac23a59a8765 [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
Angel Pons6779d232020-01-08 15:05:56 +010080var BootBlockFiles map[string]string = map[string]string{}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +020081var ROMStageFiles map[string]string = map[string]string{}
82var RAMStageFiles map[string]string = map[string]string{}
83var SMMFiles map[string]string = map[string]string{}
84var MainboardInit string
85var MainboardEnable string
86var MainboardIncludes []string
87
88type Context struct {
89 MoboID string
90 KconfigName string
91 Vendor string
92 Model string
93 BaseDirectory string
94 InfoSource DevReader
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +020095 SaneVendor string
Vladimir Serbinenko3129f792014-10-15 21:51:47 +020096}
97
98type IOAPICIRQ struct {
99 APICID int
100 IRQNO [4]int
101}
102
103var IOAPICIRQs map[PCIAddr]IOAPICIRQ = map[PCIAddr]IOAPICIRQ{}
104var KconfigBool map[string]bool = map[string]bool{}
105var KconfigComment map[string]string = map[string]string{}
106var KconfigString map[string]string = map[string]string{}
107var KconfigStringUnquoted map[string]string = map[string]string{}
108var KconfigHex map[string]uint32 = map[string]uint32{}
109var KconfigInt map[string]int = map[string]int{}
110var ROMSizeKB = 0
111var ROMProtocol = ""
112var FlashROMSupport = ""
113
114func GetLE16(inp []byte) uint16 {
115 return uint16(inp[0]) | (uint16(inp[1]) << 8)
116}
117
118func FormatHexLE16(inp []byte) string {
119 return fmt.Sprintf("0x%04x", GetLE16(inp))
120}
121
122func FormatHex32(u uint32) string {
123 return fmt.Sprintf("0x%08x", u)
124}
125
126func FormatHex8(u uint8) string {
127 return fmt.Sprintf("0x%02x", u)
128}
129
130func FormatInt32(u uint32) string {
131 return fmt.Sprintf("%d", u)
132}
133
134func FormatHexLE32(d []uint8) string {
135 u := uint32(d[0]) | (uint32(d[1]) << 8) | (uint32(d[2]) << 16) | (uint32(d[3]) << 24)
136 return FormatHex32(u)
137}
138
139func FormatBool(inp bool) string {
140 if inp {
141 return "1"
142 } else {
143 return "0"
144 }
145}
146
147func sanitize(inp string) string {
148 result := strings.ToLower(inp)
149 result = strings.Replace(result, " ", "_", -1)
150 result = strings.Replace(result, ",", "_", -1)
Arthur Heymansc8c3aca2018-01-18 22:20:25 +0100151 result = strings.Replace(result, "-", "_", -1)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200152 for strings.HasSuffix(result, ".") {
153 result = result[0 : len(result)-1]
154 }
155 return result
156}
157
Angel Pons6779d232020-01-08 15:05:56 +0100158func AddBootBlockFile(Name string, Condition string) {
159 BootBlockFiles[Name] = Condition
160}
161
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200162func AddROMStageFile(Name string, Condition string) {
163 ROMStageFiles[Name] = Condition
164}
165
166func AddRAMStageFile(Name string, Condition string) {
167 RAMStageFiles[Name] = Condition
168}
169
170func AddSMMFile(Name string, Condition string) {
171 SMMFiles[Name] = Condition
172}
173
174func IsIOPortUsedBy(ctx Context, port uint16, name string) bool {
175 for _, io := range ctx.InfoSource.GetIOPorts() {
176 if io.Start <= port && port <= io.End && io.Usage == name {
177 return true
178 }
179 }
180 return false
181}
182
183var FlagOutDir = flag.String("coreboot_dir", ".", "Resulting coreboot directory")
184
185func writeMF(mf *os.File, files map[string]string, category string) {
186 keys := []string{}
187 for file, _ := range files {
188 keys = append(keys, file)
189 }
190
191 sort.Strings(keys)
192
193 for _, file := range keys {
194 condition := files[file]
195 if condition == "" {
196 fmt.Fprintf(mf, "%s-y += %s\n", category, file)
197 } else {
Angel Pons6779d232020-01-08 15:05:56 +0100198 fmt.Fprintf(mf, "%s-$(%s) += %s\n", category, condition, file)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200199 }
200 }
201}
202
203func Create(ctx Context, name string) *os.File {
204 li := strings.LastIndex(name, "/")
205 if li > 0 {
206 os.MkdirAll(ctx.BaseDirectory+"/"+name[0:li], 0700)
207 }
208 mf, err := os.Create(ctx.BaseDirectory + "/" + name)
209 if err != nil {
210 log.Fatal(err)
211 }
212 return mf
213}
214
Angel Pons3d5d6e82020-03-18 23:55:36 +0100215func Add_gpl(f *os.File) {
216 fmt.Fprintln(f, "/* SPDX-License-Identifier: GPL-2.0-only */")
217 fmt.Fprintln(f, "/* This file is part of the coreboot project. */")
218 fmt.Fprintln(f)
Arthur Heymans59302852017-05-01 10:33:56 +0200219}
220
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200221func RestorePCI16Simple(f *os.File, pcidev PCIDevData, addr uint16) {
222 fmt.Fprintf(f, " pci_write_config16(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x);\n",
223 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
224 pcidev.ConfigDump[addr+1],
225 pcidev.ConfigDump[addr])
226}
227
228func RestorePCI32Simple(f *os.File, pcidev PCIDevData, addr uint16) {
229 fmt.Fprintf(f, " pci_write_config32(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x%02x%02x);\n",
230 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
231 pcidev.ConfigDump[addr+3],
232 pcidev.ConfigDump[addr+2],
233 pcidev.ConfigDump[addr+1],
234 pcidev.ConfigDump[addr])
235}
236
237func RestoreRCBA32(f *os.File, inteltool InteltoolData, addr uint16) {
238 fmt.Fprintf(f, "\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr])
239}
240
241type PCISlot struct {
242 PCIAddr
243 additionalComment string
244 writeEmpty bool
245}
246
247type DevTreeNode struct {
248 Bus int
249 Dev int
250 Func int
251 Disabled bool
252 Registers map[string]string
253 IOs map[uint16]uint16
254 Children []DevTreeNode
255 PCISlots []PCISlot
256 PCIController bool
257 ChildPCIBus int
258 MissingParent string
259 SubVendor uint16
260 SubSystem uint16
261 Chip string
262 Comment string
263}
264
265var DevTree DevTreeNode
266var MissingChildren map[string][]DevTreeNode = map[string][]DevTreeNode{}
267var unmatchedPCIChips map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
268var unmatchedPCIDevices map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
269
270func Offset(dt *os.File, offset int) {
271 for i := 0; i < offset; i++ {
272 fmt.Fprintf(dt, "\t")
273 }
274}
275
276func MatchDev(dev *DevTreeNode) {
277 for idx := range dev.Children {
278 MatchDev(&dev.Children[idx])
279 }
280
281 for _, slot := range dev.PCISlots {
282 slotChip, ok := unmatchedPCIChips[slot.PCIAddr]
283
284 if !ok {
285 continue
286 }
287
288 if slot.additionalComment != "" && slotChip.Comment != "" {
289 slotChip.Comment = slot.additionalComment + " " + slotChip.Comment
290 } else {
291 slotChip.Comment = slot.additionalComment + slotChip.Comment
292 }
293
294 delete(unmatchedPCIChips, slot.PCIAddr)
295 MatchDev(&slotChip)
296 dev.Children = append(dev.Children, slotChip)
297 }
298
299 if dev.PCIController {
300 for slot, slotDev := range unmatchedPCIChips {
301 if slot.Bus == dev.ChildPCIBus {
302 delete(unmatchedPCIChips, slot)
303 MatchDev(&slotDev)
304 dev.Children = append(dev.Children, slotDev)
305 }
306 }
307 }
308
309 for _, slot := range dev.PCISlots {
310 slotDev, ok := unmatchedPCIDevices[slot.PCIAddr]
311 if !ok {
312 if slot.writeEmpty {
313 dev.Children = append(dev.Children,
314 DevTreeNode{
315 Registers: map[string]string{},
316 Chip: "pci",
317 Bus: slot.Bus,
318 Dev: slot.Dev,
319 Func: slot.Func,
320 Comment: slot.additionalComment,
321 Disabled: true,
322 },
323 )
324 }
325 continue
326 }
327
328 if slot.additionalComment != "" && slotDev.Comment != "" {
329 slotDev.Comment = slot.additionalComment + " " + slotDev.Comment
330 } else {
331 slotDev.Comment = slot.additionalComment + slotDev.Comment
332 }
333
334 MatchDev(&slotDev)
335 dev.Children = append(dev.Children, slotDev)
336 delete(unmatchedPCIDevices, slot.PCIAddr)
337 }
338
339 if dev.MissingParent != "" {
340 for _, child := range MissingChildren[dev.MissingParent] {
341 MatchDev(&child)
342 dev.Children = append(dev.Children, child)
343 }
344 delete(MissingChildren, dev.MissingParent)
345 }
346
347 if dev.PCIController {
348 for slot, slotDev := range unmatchedPCIDevices {
349 if slot.Bus == dev.ChildPCIBus {
350 MatchDev(&slotDev)
351 dev.Children = append(dev.Children, slotDev)
352 delete(unmatchedPCIDevices, slot)
353 }
354 }
355 }
356}
357
358func writeOn(dt *os.File, dev DevTreeNode) {
359 if dev.Disabled {
360 fmt.Fprintf(dt, "off")
361 } else {
362 fmt.Fprintf(dt, "on")
363 }
364}
365
366func WriteDev(dt *os.File, offset int, dev DevTreeNode) {
367 Offset(dt, offset)
368 switch dev.Chip {
369 case "cpu_cluster", "lapic", "domain", "ioapic":
370 fmt.Fprintf(dt, "device %s 0x%x ", dev.Chip, dev.Dev)
371 writeOn(dt, dev)
372 case "pci", "pnp":
373 fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func)
374 writeOn(dt, dev)
375 case "i2c":
376 fmt.Fprintf(dt, "device %s %02x ", dev.Chip, dev.Dev)
377 writeOn(dt, dev)
378 default:
379 fmt.Fprintf(dt, "chip %s", dev.Chip)
380 }
381 if dev.Comment != "" {
382 fmt.Fprintf(dt, " # %s", dev.Comment)
383 }
384 fmt.Fprintf(dt, "\n")
385 if dev.Chip == "pci" && dev.SubSystem != 0 && dev.SubVendor != 0 {
386 Offset(dt, offset+1)
387 fmt.Fprintf(dt, "subsystemid 0x%04x 0x%04x\n", dev.SubVendor, dev.SubSystem)
388 }
389
390 ioapic, ok := IOAPICIRQs[PCIAddr{Bus: dev.Bus, Dev: dev.Dev, Func: dev.Func}]
391 if dev.Chip == "pci" && ok {
392 for pin, irq := range ioapic.IRQNO {
393 if irq != 0 {
394 Offset(dt, offset+1)
395 fmt.Fprintf(dt, "ioapic_irq %d INT%c 0x%x\n", ioapic.APICID, 'A'+pin, irq)
396 }
397 }
398 }
399
400 keys := []string{}
401 for reg, _ := range dev.Registers {
402 keys = append(keys, reg)
403 }
404
405 sort.Strings(keys)
406
407 for _, reg := range keys {
408 val := dev.Registers[reg]
409 Offset(dt, offset+1)
410 fmt.Fprintf(dt, "register \"%s\" = \"%s\"\n", reg, val)
411 }
412
413 ios := []int{}
414 for reg, _ := range dev.IOs {
415 ios = append(ios, int(reg))
416 }
417
418 sort.Ints(ios)
419
420 for _, reg := range ios {
421 val := dev.IOs[uint16(reg)]
422 Offset(dt, offset+1)
423 fmt.Fprintf(dt, "io 0x%x = 0x%x\n", reg, val)
424 }
425
426 for _, child := range dev.Children {
427 WriteDev(dt, offset+1, child)
428 }
429
430 Offset(dt, offset)
431 fmt.Fprintf(dt, "end\n")
432}
433
434func PutChip(domain string, cur DevTreeNode) {
435 MissingChildren[domain] = append(MissingChildren[domain], cur)
436}
437
438func PutPCIChip(addr PCIDevData, cur DevTreeNode) {
439 unmatchedPCIChips[addr.PCIAddr] = cur
440}
441
442func PutPCIDevParent(addr PCIDevData, comment string, parent string) {
443 cur := DevTreeNode{
444 Registers: map[string]string{},
445 Chip: "pci",
446 Bus: addr.Bus,
447 Dev: addr.Dev,
448 Func: addr.Func,
449 MissingParent: parent,
450 Comment: comment,
451 }
452 if addr.ConfigDump[0xa] == 0x04 && addr.ConfigDump[0xb] == 0x06 {
453 cur.PCIController = true
454 cur.ChildPCIBus = int(addr.ConfigDump[0x19])
455
456 loopCtr := 0
457 for capPtr := addr.ConfigDump[0x34]; capPtr != 0; capPtr = addr.ConfigDump[capPtr+1] {
458 /* Avoid hangs. There are only 0x100 different possible values for capPtr.
459 If we iterate longer than that, we're in endless loop. */
460 loopCtr++
461 if loopCtr > 0x100 {
462 break
463 }
464 if addr.ConfigDump[capPtr] == 0x0d {
465 cur.SubVendor = GetLE16(addr.ConfigDump[capPtr+4 : capPtr+6])
466 cur.SubSystem = GetLE16(addr.ConfigDump[capPtr+6 : capPtr+8])
467 }
468 }
469 } else {
470 cur.SubVendor = GetLE16(addr.ConfigDump[0x2c:0x2e])
471 cur.SubSystem = GetLE16(addr.ConfigDump[0x2e:0x30])
472 }
473 unmatchedPCIDevices[addr.PCIAddr] = cur
474}
475
476func PutPCIDev(addr PCIDevData, comment string) {
477 PutPCIDevParent(addr, comment, "")
478}
479
480type GenericPCI struct {
481 Comment string
482 Bus0Subdiv string
483 MissingParent string
484}
485
486type GenericVGA struct {
487 GenericPCI
488}
489
490type DSDTInclude struct {
491 Comment string
492 File string
493}
494
495type DSDTDefine struct {
496 Key string
497 Comment string
498 Value string
499}
500
501var DSDTIncludes []DSDTInclude
502var DSDTPCI0Includes []DSDTInclude
503var DSDTDefines []DSDTDefine
504
505func (g GenericPCI) Scan(ctx Context, addr PCIDevData) {
506 PutPCIDevParent(addr, g.Comment, g.MissingParent)
507}
508
Iru Caicd980ab2019-01-14 20:38:16 +0800509var IGDEnabled bool = false
510
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200511func (g GenericVGA) Scan(ctx Context, addr PCIDevData) {
512 KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x",
513 addr.PCIVenID,
514 addr.PCIDevID)
515 KconfigString["VGA_BIOS_FILE"] = fmt.Sprintf("pci%04x,%04x.rom",
516 addr.PCIVenID,
517 addr.PCIDevID)
518 PutPCIDevParent(addr, g.Comment, g.MissingParent)
Iru Caicd980ab2019-01-14 20:38:16 +0800519 IGDEnabled = true
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200520}
521
522func makeKconfigName(ctx Context) {
523 kn := Create(ctx, "Kconfig.name")
524 defer kn.Close()
525
526 fmt.Fprintf(kn, "config %s\n\tbool \"%s\"\n", ctx.KconfigName, ctx.Model)
527}
528
529func makeComment(name string) string {
530 cmt, ok := KconfigComment[name]
531 if !ok {
532 return ""
533 }
534 return " # " + cmt
535}
536
537func makeKconfig(ctx Context) {
538 kc := Create(ctx, "Kconfig")
539 defer kc.Close()
540
541 fmt.Fprintf(kc, "if %s\n\n", ctx.KconfigName)
542
Elyes HAOUASf0c5be22018-11-27 20:36:44 +0100543 fmt.Fprintf(kc, "config BOARD_SPECIFIC_OPTIONS\n\tdef_bool y\n")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200544 keys := []string{}
545 for name, val := range KconfigBool {
546 if val {
547 keys = append(keys, name)
548 }
549 }
550
551 sort.Strings(keys)
552
553 for _, name := range keys {
554 fmt.Fprintf(kc, "\tselect %s%s\n", name, makeComment(name))
555 }
556
557 keys = nil
558 for name, val := range KconfigBool {
559 if !val {
560 keys = append(keys, name)
561 }
562 }
563
564 sort.Strings(keys)
565
566 for _, name := range keys {
567 fmt.Fprintf(kc, `
568config %s%s
569 bool
570 default n
571`, name, makeComment(name))
572 }
573
574 keys = nil
575 for name, _ := range KconfigStringUnquoted {
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), KconfigStringUnquoted[name])
587 }
588
589 keys = nil
590 for name, _ := range KconfigString {
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 string
600 default "%s"
601`, name, makeComment(name), KconfigString[name])
602 }
603
604 keys = nil
605 for name, _ := range KconfigHex {
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 hex
615 default 0x%x
616`, name, makeComment(name), KconfigHex[name])
617 }
618
619 keys = nil
620 for name, _ := range KconfigInt {
621 keys = append(keys, name)
622 }
623
624 sort.Strings(keys)
625
626 for _, name := range keys {
627 fmt.Fprintf(kc, `
628config %s%s
629 int
630 default %d
631`, name, makeComment(name), KconfigInt[name])
632 }
633
634 fmt.Fprintf(kc, "endif\n")
635}
636
637const MoboDir = "/src/mainboard/"
638
639func makeVendor(ctx Context) {
640 vendor := ctx.Vendor
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200641 vendorSane := ctx.SaneVendor
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200642 vendorDir := *FlagOutDir + MoboDir + vendorSane
643 vendorUpper := strings.ToUpper(vendorSane)
644 kconfig := vendorDir + "/Kconfig"
645 if _, err := os.Stat(kconfig); os.IsNotExist(err) {
646 f, err := os.Create(kconfig)
647 if err != nil {
648 log.Fatal(err)
649 }
650 defer f.Close()
651 f.WriteString(`if VENDOR_` + vendorUpper + `
652
653choice
654 prompt "Mainboard model"
655
656source "src/mainboard/` + vendorSane + `/*/Kconfig.name"
657
658endchoice
659
660source "src/mainboard/` + vendorSane + `/*/Kconfig"
661
662config MAINBOARD_VENDOR
663 string
664 default "` + vendor + `"
665
666endif # VENDOR_` + vendorUpper + "\n")
667 }
668 kconfigName := vendorDir + "/Kconfig.name"
669 if _, err := os.Stat(kconfigName); os.IsNotExist(err) {
670 f, err := os.Create(kconfigName)
671 if err != nil {
672 log.Fatal(err)
673 }
674 defer f.Close()
675 f.WriteString(`config VENDOR_` + vendorUpper + `
676 bool "` + vendor + `"
677`)
678 }
679
680}
681
682func GuessECGPE(ctx Context) int {
683 /* FIXME:XX Use iasl -d and/or better parsing */
684 dsdt := ctx.InfoSource.GetACPI()["DSDT"]
685 idx := bytes.Index(dsdt, []byte{0x08, '_', 'G', 'P', 'E', 0x0a}) /* Name (_GPE, byte). */
686 if idx > 0 {
687 return int(dsdt[idx+6])
688 }
689 return -1
690}
691
692func GuessSPDMap(ctx Context) []uint8 {
693 dmi := ctx.InfoSource.GetDMI()
694
695 if dmi.Vendor == "LENOVO" {
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200696 return []uint8{0x50, 0x52, 0x51, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200697 }
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200698 return []uint8{0x50, 0x51, 0x52, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200699}
700
701func main() {
702 flag.Parse()
703
704 ctx := Context{}
705
706 ctx.InfoSource = MakeLogReader()
707
708 dmi := ctx.InfoSource.GetDMI()
709
710 ctx.Vendor = dmi.Vendor
711
712 if dmi.Vendor == "LENOVO" {
713 ctx.Model = dmi.Version
714 } else {
715 ctx.Model = dmi.Model
716 }
717
718 if dmi.IsLaptop {
719 KconfigBool["SYSTEM_TYPE_LAPTOP"] = true
720 }
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200721 ctx.SaneVendor = sanitize(ctx.Vendor)
722 for {
723 last := ctx.SaneVendor
724 for _, suf := range []string{"_inc", "_co", "_corp"} {
725 ctx.SaneVendor = strings.TrimSuffix(ctx.SaneVendor, suf)
726 }
727 if last == ctx.SaneVendor {
728 break
729 }
730 }
731 ctx.MoboID = ctx.SaneVendor + "/" + sanitize(ctx.Model)
732 ctx.KconfigName = "BOARD_" + strings.ToUpper(ctx.SaneVendor+"_"+sanitize(ctx.Model))
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200733 ctx.BaseDirectory = *FlagOutDir + MoboDir + ctx.MoboID
734 KconfigStringUnquoted["MAINBOARD_DIR"] = ctx.MoboID
735 KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model
736
737 os.MkdirAll(ctx.BaseDirectory, 0700)
738
739 makeVendor(ctx)
740
741 ScanRoot(ctx)
742
Iru Caicd980ab2019-01-14 20:38:16 +0800743 if IGDEnabled {
744 KconfigBool["MAINBOARD_HAS_LIBGFXINIT"] = true
745 KconfigComment["MAINBOARD_HAS_LIBGFXINIT"] = "FIXME: check this"
746 AddRAMStageFile("gma-mainboard.ads", "CONFIG_MAINBOARD_USE_LIBGFXINIT")
747 }
748
Angel Pons6779d232020-01-08 15:05:56 +0100749 if len(BootBlockFiles) > 0 || len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200750 mf := Create(ctx, "Makefile.inc")
751 defer mf.Close()
Angel Pons6779d232020-01-08 15:05:56 +0100752 writeMF(mf, BootBlockFiles, "bootblock")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200753 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 != "" {
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200773 mainboard.WriteString(`static void mainboard_init(struct device *dev)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200774{
775` + MainboardInit + "}\n\n")
776 }
777 if MainboardInit != "" || MainboardEnable != "" {
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200778 mainboard.WriteString("static void mainboard_enable(struct device *dev)\n{\n")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200779 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
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200791 bi := Create(ctx, "board_info.txt")
792 defer bi.Close()
793
794 fixme := ""
795
796 if dmi.IsLaptop {
797 bi.WriteString("Category: laptop\n")
798 } else {
799 bi.WriteString("Category: desktop\n")
800 fixme += "check category, "
801 }
802
803 missing := "ROM package, ROM socketed"
804
805 if ROMProtocol != "" {
806 fmt.Fprintf(bi, "ROM protocol: %s\n", ROMProtocol)
807 } else {
808 missing += ", ROM protocol"
809 }
810
811 if FlashROMSupport != "" {
812 fmt.Fprintf(bi, "Flashrom support: %s\n", FlashROMSupport)
813 } else {
814 missing += ", Flashrom support"
815 }
816
817 missing += ", Release year"
818
819 if fixme != "" {
820 fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing)
821 } else {
822 fmt.Fprintf(bi, "FIXME: put %s\n", missing)
823 }
824
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200825 if ROMSizeKB == 0 {
826 KconfigBool["BOARD_ROMSIZE_KB_2048"] = true
827 KconfigComment["BOARD_ROMSIZE_KB_2048"] = "FIXME: correct this"
828 } else {
829 KconfigBool[fmt.Sprintf("BOARD_ROMSIZE_KB_%d", ROMSizeKB)] = true
830 }
831
832 makeKconfig(ctx)
833 makeKconfigName(ctx)
834
835 dsdt := Create(ctx, "dsdt.asl")
836 defer dsdt.Close()
837
838 for _, define := range DSDTDefines {
839 if define.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100840 fmt.Fprintf(dsdt, "\t/* %s. */\n", define.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200841 }
842 dsdt.WriteString("#define " + define.Key + " " + define.Value + "\n")
843 }
844
845 dsdt.WriteString(
Angel Ponsca623342019-01-16 21:55:55 +0100846 `
Angel Pons6779d232020-01-08 15:05:56 +0100847
Angel Ponsca623342019-01-16 21:55:55 +0100848#include <arch/acpi.h>
Angel Pons6779d232020-01-08 15:05:56 +0100849
Elyes HAOUAS6d19a202018-11-22 11:15:29 +0100850DefinitionBlock(
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200851 "dsdt.aml",
852 "DSDT",
Angel Pons6779d232020-01-08 15:05:56 +0100853 0x02, /* DSDT revision: ACPI 2.0 and up */
Elyes HAOUAS6d19a202018-11-22 11:15:29 +0100854 OEM_ID,
855 ACPI_TABLE_CREATOR,
Angel Pons6779d232020-01-08 15:05:56 +0100856 0x20141018 /* OEM revision */
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200857)
858{
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200859 #include "acpi/platform.asl"
860`)
861
862 for _, x := range DSDTIncludes {
863 if x.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100864 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200865 }
866 fmt.Fprintf(dsdt, "\t#include <%s>\n", x.File)
867 }
868
869 dsdt.WriteString(`
Angel Ponsca623342019-01-16 21:55:55 +0100870 Device (\_SB.PCI0)
871 {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200872`)
873 for _, x := range DSDTPCI0Includes {
874 if x.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100875 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200876 }
877 fmt.Fprintf(dsdt, "\t\t#include <%s>\n", x.File)
878 }
879 dsdt.WriteString(
Angel Ponsca623342019-01-16 21:55:55 +0100880 ` }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200881}
882`)
883
Iru Caicd980ab2019-01-14 20:38:16 +0800884 if IGDEnabled {
885 gma := Create(ctx, "gma-mainboard.ads")
886 defer gma.Close()
887
Angel Pons3d5d6e82020-03-18 23:55:36 +0100888 gma.WriteString(`-- SPDX-License-Identifier: GPL-2.0-or-later
Iru Caicd980ab2019-01-14 20:38:16 +0800889-- This file is part of the coreboot project.
Iru Caicd980ab2019-01-14 20:38:16 +0800890
891with HW.GFX.GMA;
892with HW.GFX.GMA.Display_Probing;
893
894use HW.GFX.GMA;
895use HW.GFX.GMA.Display_Probing;
896
897private package GMA.Mainboard is
898
899 -- FIXME: check this
900 ports : constant Port_List :=
901 (DP1,
902 DP2,
903 DP3,
904 HDMI1,
905 HDMI2,
906 HDMI3,
907 Analog,
Nico Huber4ce52902020-02-15 17:56:01 +0100908 LVDS,
909 eDP);
Iru Caicd980ab2019-01-14 20:38:16 +0800910
911end GMA.Mainboard;
912`)
913 }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200914}