blob: ab49a14a9d06da974d3a5e18d757bfeeb2863b45 [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)
Arthur Heymansc8c3aca2018-01-18 22:20:25 +0100150 result = strings.Replace(result, "-", "_", -1)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200151 for strings.HasSuffix(result, ".") {
152 result = result[0 : len(result)-1]
153 }
154 return result
155}
156
157func AddROMStageFile(Name string, Condition string) {
158 ROMStageFiles[Name] = Condition
159}
160
161func AddRAMStageFile(Name string, Condition string) {
162 RAMStageFiles[Name] = Condition
163}
164
165func AddSMMFile(Name string, Condition string) {
166 SMMFiles[Name] = Condition
167}
168
169func IsIOPortUsedBy(ctx Context, port uint16, name string) bool {
170 for _, io := range ctx.InfoSource.GetIOPorts() {
171 if io.Start <= port && port <= io.End && io.Usage == name {
172 return true
173 }
174 }
175 return false
176}
177
178var FlagOutDir = flag.String("coreboot_dir", ".", "Resulting coreboot directory")
179
180func writeMF(mf *os.File, files map[string]string, category string) {
181 keys := []string{}
182 for file, _ := range files {
183 keys = append(keys, file)
184 }
185
186 sort.Strings(keys)
187
188 for _, file := range keys {
189 condition := files[file]
190 if condition == "" {
191 fmt.Fprintf(mf, "%s-y += %s\n", category, file)
192 } else {
193 fmt.Fprintf(mf, "%s-$(%s) += %s\n", category,
194 condition, file)
195 }
196 }
197}
198
199func Create(ctx Context, name string) *os.File {
200 li := strings.LastIndex(name, "/")
201 if li > 0 {
202 os.MkdirAll(ctx.BaseDirectory+"/"+name[0:li], 0700)
203 }
204 mf, err := os.Create(ctx.BaseDirectory + "/" + name)
205 if err != nil {
206 log.Fatal(err)
207 }
208 return mf
209}
210
Arthur Heymans59302852017-05-01 10:33:56 +0200211func Add_gpl(fp *os.File) {
212 fp.WriteString(`/*
213 * This file is part of the coreboot project.
214 *
215 * Copyright (C) 2008-2009 coresystems GmbH
216 * Copyright (C) 2014 Vladimir Serbinenko
217 *
218 * This program is free software; you can redistribute it and/or
219 * modify it under the terms of the GNU General Public License as
220 * published by the Free Software Foundation; version 2 of
221 * the License.
222 *
223 * This program is distributed in the hope that it will be useful,
224 * but WITHOUT ANY WARRANTY; without even the implied warranty of
225 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
226 * GNU General Public License for more details.
227 */
228
229`)
230}
231
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200232func RestorePCI16Simple(f *os.File, pcidev PCIDevData, addr uint16) {
233 fmt.Fprintf(f, " pci_write_config16(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x);\n",
234 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
235 pcidev.ConfigDump[addr+1],
236 pcidev.ConfigDump[addr])
237}
238
239func RestorePCI32Simple(f *os.File, pcidev PCIDevData, addr uint16) {
240 fmt.Fprintf(f, " pci_write_config32(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x%02x%02x);\n",
241 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
242 pcidev.ConfigDump[addr+3],
243 pcidev.ConfigDump[addr+2],
244 pcidev.ConfigDump[addr+1],
245 pcidev.ConfigDump[addr])
246}
247
248func RestoreRCBA32(f *os.File, inteltool InteltoolData, addr uint16) {
249 fmt.Fprintf(f, "\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr])
250}
251
252type PCISlot struct {
253 PCIAddr
254 additionalComment string
255 writeEmpty bool
256}
257
258type DevTreeNode struct {
259 Bus int
260 Dev int
261 Func int
262 Disabled bool
263 Registers map[string]string
264 IOs map[uint16]uint16
265 Children []DevTreeNode
266 PCISlots []PCISlot
267 PCIController bool
268 ChildPCIBus int
269 MissingParent string
270 SubVendor uint16
271 SubSystem uint16
272 Chip string
273 Comment string
274}
275
276var DevTree DevTreeNode
277var MissingChildren map[string][]DevTreeNode = map[string][]DevTreeNode{}
278var unmatchedPCIChips map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
279var unmatchedPCIDevices map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
280
281func Offset(dt *os.File, offset int) {
282 for i := 0; i < offset; i++ {
283 fmt.Fprintf(dt, "\t")
284 }
285}
286
287func MatchDev(dev *DevTreeNode) {
288 for idx := range dev.Children {
289 MatchDev(&dev.Children[idx])
290 }
291
292 for _, slot := range dev.PCISlots {
293 slotChip, ok := unmatchedPCIChips[slot.PCIAddr]
294
295 if !ok {
296 continue
297 }
298
299 if slot.additionalComment != "" && slotChip.Comment != "" {
300 slotChip.Comment = slot.additionalComment + " " + slotChip.Comment
301 } else {
302 slotChip.Comment = slot.additionalComment + slotChip.Comment
303 }
304
305 delete(unmatchedPCIChips, slot.PCIAddr)
306 MatchDev(&slotChip)
307 dev.Children = append(dev.Children, slotChip)
308 }
309
310 if dev.PCIController {
311 for slot, slotDev := range unmatchedPCIChips {
312 if slot.Bus == dev.ChildPCIBus {
313 delete(unmatchedPCIChips, slot)
314 MatchDev(&slotDev)
315 dev.Children = append(dev.Children, slotDev)
316 }
317 }
318 }
319
320 for _, slot := range dev.PCISlots {
321 slotDev, ok := unmatchedPCIDevices[slot.PCIAddr]
322 if !ok {
323 if slot.writeEmpty {
324 dev.Children = append(dev.Children,
325 DevTreeNode{
326 Registers: map[string]string{},
327 Chip: "pci",
328 Bus: slot.Bus,
329 Dev: slot.Dev,
330 Func: slot.Func,
331 Comment: slot.additionalComment,
332 Disabled: true,
333 },
334 )
335 }
336 continue
337 }
338
339 if slot.additionalComment != "" && slotDev.Comment != "" {
340 slotDev.Comment = slot.additionalComment + " " + slotDev.Comment
341 } else {
342 slotDev.Comment = slot.additionalComment + slotDev.Comment
343 }
344
345 MatchDev(&slotDev)
346 dev.Children = append(dev.Children, slotDev)
347 delete(unmatchedPCIDevices, slot.PCIAddr)
348 }
349
350 if dev.MissingParent != "" {
351 for _, child := range MissingChildren[dev.MissingParent] {
352 MatchDev(&child)
353 dev.Children = append(dev.Children, child)
354 }
355 delete(MissingChildren, dev.MissingParent)
356 }
357
358 if dev.PCIController {
359 for slot, slotDev := range unmatchedPCIDevices {
360 if slot.Bus == dev.ChildPCIBus {
361 MatchDev(&slotDev)
362 dev.Children = append(dev.Children, slotDev)
363 delete(unmatchedPCIDevices, slot)
364 }
365 }
366 }
367}
368
369func writeOn(dt *os.File, dev DevTreeNode) {
370 if dev.Disabled {
371 fmt.Fprintf(dt, "off")
372 } else {
373 fmt.Fprintf(dt, "on")
374 }
375}
376
377func WriteDev(dt *os.File, offset int, dev DevTreeNode) {
378 Offset(dt, offset)
379 switch dev.Chip {
380 case "cpu_cluster", "lapic", "domain", "ioapic":
381 fmt.Fprintf(dt, "device %s 0x%x ", dev.Chip, dev.Dev)
382 writeOn(dt, dev)
383 case "pci", "pnp":
384 fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func)
385 writeOn(dt, dev)
386 case "i2c":
387 fmt.Fprintf(dt, "device %s %02x ", dev.Chip, dev.Dev)
388 writeOn(dt, dev)
389 default:
390 fmt.Fprintf(dt, "chip %s", dev.Chip)
391 }
392 if dev.Comment != "" {
393 fmt.Fprintf(dt, " # %s", dev.Comment)
394 }
395 fmt.Fprintf(dt, "\n")
396 if dev.Chip == "pci" && dev.SubSystem != 0 && dev.SubVendor != 0 {
397 Offset(dt, offset+1)
398 fmt.Fprintf(dt, "subsystemid 0x%04x 0x%04x\n", dev.SubVendor, dev.SubSystem)
399 }
400
401 ioapic, ok := IOAPICIRQs[PCIAddr{Bus: dev.Bus, Dev: dev.Dev, Func: dev.Func}]
402 if dev.Chip == "pci" && ok {
403 for pin, irq := range ioapic.IRQNO {
404 if irq != 0 {
405 Offset(dt, offset+1)
406 fmt.Fprintf(dt, "ioapic_irq %d INT%c 0x%x\n", ioapic.APICID, 'A'+pin, irq)
407 }
408 }
409 }
410
411 keys := []string{}
412 for reg, _ := range dev.Registers {
413 keys = append(keys, reg)
414 }
415
416 sort.Strings(keys)
417
418 for _, reg := range keys {
419 val := dev.Registers[reg]
420 Offset(dt, offset+1)
421 fmt.Fprintf(dt, "register \"%s\" = \"%s\"\n", reg, val)
422 }
423
424 ios := []int{}
425 for reg, _ := range dev.IOs {
426 ios = append(ios, int(reg))
427 }
428
429 sort.Ints(ios)
430
431 for _, reg := range ios {
432 val := dev.IOs[uint16(reg)]
433 Offset(dt, offset+1)
434 fmt.Fprintf(dt, "io 0x%x = 0x%x\n", reg, val)
435 }
436
437 for _, child := range dev.Children {
438 WriteDev(dt, offset+1, child)
439 }
440
441 Offset(dt, offset)
442 fmt.Fprintf(dt, "end\n")
443}
444
445func PutChip(domain string, cur DevTreeNode) {
446 MissingChildren[domain] = append(MissingChildren[domain], cur)
447}
448
449func PutPCIChip(addr PCIDevData, cur DevTreeNode) {
450 unmatchedPCIChips[addr.PCIAddr] = cur
451}
452
453func PutPCIDevParent(addr PCIDevData, comment string, parent string) {
454 cur := DevTreeNode{
455 Registers: map[string]string{},
456 Chip: "pci",
457 Bus: addr.Bus,
458 Dev: addr.Dev,
459 Func: addr.Func,
460 MissingParent: parent,
461 Comment: comment,
462 }
463 if addr.ConfigDump[0xa] == 0x04 && addr.ConfigDump[0xb] == 0x06 {
464 cur.PCIController = true
465 cur.ChildPCIBus = int(addr.ConfigDump[0x19])
466
467 loopCtr := 0
468 for capPtr := addr.ConfigDump[0x34]; capPtr != 0; capPtr = addr.ConfigDump[capPtr+1] {
469 /* Avoid hangs. There are only 0x100 different possible values for capPtr.
470 If we iterate longer than that, we're in endless loop. */
471 loopCtr++
472 if loopCtr > 0x100 {
473 break
474 }
475 if addr.ConfigDump[capPtr] == 0x0d {
476 cur.SubVendor = GetLE16(addr.ConfigDump[capPtr+4 : capPtr+6])
477 cur.SubSystem = GetLE16(addr.ConfigDump[capPtr+6 : capPtr+8])
478 }
479 }
480 } else {
481 cur.SubVendor = GetLE16(addr.ConfigDump[0x2c:0x2e])
482 cur.SubSystem = GetLE16(addr.ConfigDump[0x2e:0x30])
483 }
484 unmatchedPCIDevices[addr.PCIAddr] = cur
485}
486
487func PutPCIDev(addr PCIDevData, comment string) {
488 PutPCIDevParent(addr, comment, "")
489}
490
491type GenericPCI struct {
492 Comment string
493 Bus0Subdiv string
494 MissingParent string
495}
496
497type GenericVGA struct {
498 GenericPCI
499}
500
501type DSDTInclude struct {
502 Comment string
503 File string
504}
505
506type DSDTDefine struct {
507 Key string
508 Comment string
509 Value string
510}
511
512var DSDTIncludes []DSDTInclude
513var DSDTPCI0Includes []DSDTInclude
514var DSDTDefines []DSDTDefine
515
516func (g GenericPCI) Scan(ctx Context, addr PCIDevData) {
517 PutPCIDevParent(addr, g.Comment, g.MissingParent)
518}
519
Iru Caicd980ab2019-01-14 20:38:16 +0800520var IGDEnabled bool = false
521
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200522func (g GenericVGA) Scan(ctx Context, addr PCIDevData) {
523 KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x",
524 addr.PCIVenID,
525 addr.PCIDevID)
526 KconfigString["VGA_BIOS_FILE"] = fmt.Sprintf("pci%04x,%04x.rom",
527 addr.PCIVenID,
528 addr.PCIDevID)
529 PutPCIDevParent(addr, g.Comment, g.MissingParent)
Iru Caicd980ab2019-01-14 20:38:16 +0800530 IGDEnabled = true
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200531}
532
533func makeKconfigName(ctx Context) {
534 kn := Create(ctx, "Kconfig.name")
535 defer kn.Close()
536
537 fmt.Fprintf(kn, "config %s\n\tbool \"%s\"\n", ctx.KconfigName, ctx.Model)
538}
539
540func makeComment(name string) string {
541 cmt, ok := KconfigComment[name]
542 if !ok {
543 return ""
544 }
545 return " # " + cmt
546}
547
548func makeKconfig(ctx Context) {
549 kc := Create(ctx, "Kconfig")
550 defer kc.Close()
551
552 fmt.Fprintf(kc, "if %s\n\n", ctx.KconfigName)
553
Elyes HAOUASf0c5be22018-11-27 20:36:44 +0100554 fmt.Fprintf(kc, "config BOARD_SPECIFIC_OPTIONS\n\tdef_bool y\n")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200555 keys := []string{}
556 for name, val := range KconfigBool {
557 if val {
558 keys = append(keys, name)
559 }
560 }
561
562 sort.Strings(keys)
563
564 for _, name := range keys {
565 fmt.Fprintf(kc, "\tselect %s%s\n", name, makeComment(name))
566 }
567
568 keys = nil
569 for name, val := range KconfigBool {
570 if !val {
571 keys = append(keys, name)
572 }
573 }
574
575 sort.Strings(keys)
576
577 for _, name := range keys {
578 fmt.Fprintf(kc, `
579config %s%s
580 bool
581 default n
582`, name, makeComment(name))
583 }
584
585 keys = nil
586 for name, _ := range KconfigStringUnquoted {
587 keys = append(keys, name)
588 }
589
590 sort.Strings(keys)
591
592 for _, name := range keys {
593 fmt.Fprintf(kc, `
594config %s%s
595 string
596 default %s
597`, name, makeComment(name), KconfigStringUnquoted[name])
598 }
599
600 keys = nil
601 for name, _ := range KconfigString {
602 keys = append(keys, name)
603 }
604
605 sort.Strings(keys)
606
607 for _, name := range keys {
608 fmt.Fprintf(kc, `
609config %s%s
610 string
611 default "%s"
612`, name, makeComment(name), KconfigString[name])
613 }
614
615 keys = nil
616 for name, _ := range KconfigHex {
617 keys = append(keys, name)
618 }
619
620 sort.Strings(keys)
621
622 for _, name := range keys {
623 fmt.Fprintf(kc, `
624config %s%s
625 hex
626 default 0x%x
627`, name, makeComment(name), KconfigHex[name])
628 }
629
630 keys = nil
631 for name, _ := range KconfigInt {
632 keys = append(keys, name)
633 }
634
635 sort.Strings(keys)
636
637 for _, name := range keys {
638 fmt.Fprintf(kc, `
639config %s%s
640 int
641 default %d
642`, name, makeComment(name), KconfigInt[name])
643 }
644
645 fmt.Fprintf(kc, "endif\n")
646}
647
648const MoboDir = "/src/mainboard/"
649
650func makeVendor(ctx Context) {
651 vendor := ctx.Vendor
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200652 vendorSane := ctx.SaneVendor
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200653 vendorDir := *FlagOutDir + MoboDir + vendorSane
654 vendorUpper := strings.ToUpper(vendorSane)
655 kconfig := vendorDir + "/Kconfig"
656 if _, err := os.Stat(kconfig); os.IsNotExist(err) {
657 f, err := os.Create(kconfig)
658 if err != nil {
659 log.Fatal(err)
660 }
661 defer f.Close()
662 f.WriteString(`if VENDOR_` + vendorUpper + `
663
664choice
665 prompt "Mainboard model"
666
667source "src/mainboard/` + vendorSane + `/*/Kconfig.name"
668
669endchoice
670
671source "src/mainboard/` + vendorSane + `/*/Kconfig"
672
673config MAINBOARD_VENDOR
674 string
675 default "` + vendor + `"
676
677endif # VENDOR_` + vendorUpper + "\n")
678 }
679 kconfigName := vendorDir + "/Kconfig.name"
680 if _, err := os.Stat(kconfigName); os.IsNotExist(err) {
681 f, err := os.Create(kconfigName)
682 if err != nil {
683 log.Fatal(err)
684 }
685 defer f.Close()
686 f.WriteString(`config VENDOR_` + vendorUpper + `
687 bool "` + vendor + `"
688`)
689 }
690
691}
692
693func GuessECGPE(ctx Context) int {
694 /* FIXME:XX Use iasl -d and/or better parsing */
695 dsdt := ctx.InfoSource.GetACPI()["DSDT"]
696 idx := bytes.Index(dsdt, []byte{0x08, '_', 'G', 'P', 'E', 0x0a}) /* Name (_GPE, byte). */
697 if idx > 0 {
698 return int(dsdt[idx+6])
699 }
700 return -1
701}
702
703func GuessSPDMap(ctx Context) []uint8 {
704 dmi := ctx.InfoSource.GetDMI()
705
706 if dmi.Vendor == "LENOVO" {
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200707 return []uint8{0x50, 0x52, 0x51, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200708 }
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200709 return []uint8{0x50, 0x51, 0x52, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200710}
711
712func main() {
713 flag.Parse()
714
715 ctx := Context{}
716
717 ctx.InfoSource = MakeLogReader()
718
719 dmi := ctx.InfoSource.GetDMI()
720
721 ctx.Vendor = dmi.Vendor
722
723 if dmi.Vendor == "LENOVO" {
724 ctx.Model = dmi.Version
725 } else {
726 ctx.Model = dmi.Model
727 }
728
729 if dmi.IsLaptop {
730 KconfigBool["SYSTEM_TYPE_LAPTOP"] = true
731 }
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200732 ctx.SaneVendor = sanitize(ctx.Vendor)
733 for {
734 last := ctx.SaneVendor
735 for _, suf := range []string{"_inc", "_co", "_corp"} {
736 ctx.SaneVendor = strings.TrimSuffix(ctx.SaneVendor, suf)
737 }
738 if last == ctx.SaneVendor {
739 break
740 }
741 }
742 ctx.MoboID = ctx.SaneVendor + "/" + sanitize(ctx.Model)
743 ctx.KconfigName = "BOARD_" + strings.ToUpper(ctx.SaneVendor+"_"+sanitize(ctx.Model))
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200744 ctx.BaseDirectory = *FlagOutDir + MoboDir + ctx.MoboID
745 KconfigStringUnquoted["MAINBOARD_DIR"] = ctx.MoboID
746 KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model
747
748 os.MkdirAll(ctx.BaseDirectory, 0700)
749
750 makeVendor(ctx)
751
752 ScanRoot(ctx)
753
Iru Caicd980ab2019-01-14 20:38:16 +0800754 if IGDEnabled {
755 KconfigBool["MAINBOARD_HAS_LIBGFXINIT"] = true
756 KconfigComment["MAINBOARD_HAS_LIBGFXINIT"] = "FIXME: check this"
757 AddRAMStageFile("gma-mainboard.ads", "CONFIG_MAINBOARD_USE_LIBGFXINIT")
758 }
759
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200760 if len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 {
761 mf := Create(ctx, "Makefile.inc")
762 defer mf.Close()
763 writeMF(mf, ROMStageFiles, "romstage")
764 writeMF(mf, RAMStageFiles, "ramstage")
765 writeMF(mf, SMMFiles, "smm")
766 }
767
768 devtree := Create(ctx, "devicetree.cb")
769 defer devtree.Close()
770
771 MatchDev(&DevTree)
772 WriteDev(devtree, 0, DevTree)
773
774 if MainboardInit != "" || MainboardEnable != "" || MainboardIncludes != nil {
775 mainboard := Create(ctx, "mainboard.c")
776 defer mainboard.Close()
777 mainboard.WriteString("#include <device/device.h>\n")
778 for _, include := range MainboardIncludes {
779 mainboard.WriteString("#include <" + include + ">\n")
780 }
781 mainboard.WriteString("\n")
782 if MainboardInit != "" {
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200783 mainboard.WriteString(`static void mainboard_init(struct device *dev)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200784{
785` + MainboardInit + "}\n\n")
786 }
787 if MainboardInit != "" || MainboardEnable != "" {
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200788 mainboard.WriteString("static void mainboard_enable(struct device *dev)\n{\n")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200789 if MainboardInit != "" {
790 mainboard.WriteString("\tdev->ops->init = mainboard_init;\n\n")
791 }
792 mainboard.WriteString(MainboardEnable)
793 mainboard.WriteString("}\n\n")
794 mainboard.WriteString(`struct chip_operations mainboard_ops = {
795 .enable_dev = mainboard_enable,
796};
797`)
798 }
799 }
800
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200801 bi := Create(ctx, "board_info.txt")
802 defer bi.Close()
803
804 fixme := ""
805
806 if dmi.IsLaptop {
807 bi.WriteString("Category: laptop\n")
808 } else {
809 bi.WriteString("Category: desktop\n")
810 fixme += "check category, "
811 }
812
813 missing := "ROM package, ROM socketed"
814
815 if ROMProtocol != "" {
816 fmt.Fprintf(bi, "ROM protocol: %s\n", ROMProtocol)
817 } else {
818 missing += ", ROM protocol"
819 }
820
821 if FlashROMSupport != "" {
822 fmt.Fprintf(bi, "Flashrom support: %s\n", FlashROMSupport)
823 } else {
824 missing += ", Flashrom support"
825 }
826
827 missing += ", Release year"
828
829 if fixme != "" {
830 fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing)
831 } else {
832 fmt.Fprintf(bi, "FIXME: put %s\n", missing)
833 }
834
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200835 if ROMSizeKB == 0 {
836 KconfigBool["BOARD_ROMSIZE_KB_2048"] = true
837 KconfigComment["BOARD_ROMSIZE_KB_2048"] = "FIXME: correct this"
838 } else {
839 KconfigBool[fmt.Sprintf("BOARD_ROMSIZE_KB_%d", ROMSizeKB)] = true
840 }
841
842 makeKconfig(ctx)
843 makeKconfigName(ctx)
844
845 dsdt := Create(ctx, "dsdt.asl")
846 defer dsdt.Close()
847
848 for _, define := range DSDTDefines {
849 if define.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100850 fmt.Fprintf(dsdt, "\t/* %s. */\n", define.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200851 }
852 dsdt.WriteString("#define " + define.Key + " " + define.Value + "\n")
853 }
854
855 dsdt.WriteString(
Angel Ponsca623342019-01-16 21:55:55 +0100856 `
857#include <arch/acpi.h>
Elyes HAOUAS6d19a202018-11-22 11:15:29 +0100858DefinitionBlock(
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200859 "dsdt.aml",
860 "DSDT",
Elyes HAOUAS0cca6e22018-11-13 14:23:29 +0100861 0x02, // DSDT revision: ACPI 2.0 and up
Elyes HAOUAS6d19a202018-11-22 11:15:29 +0100862 OEM_ID,
863 ACPI_TABLE_CREATOR,
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200864 0x20141018 // OEM revision
865)
866{
Angel Ponsca623342019-01-16 21:55:55 +0100867 /* Some generic macros */
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200868 #include "acpi/platform.asl"
869`)
870
871 for _, x := range DSDTIncludes {
872 if x.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100873 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200874 }
875 fmt.Fprintf(dsdt, "\t#include <%s>\n", x.File)
876 }
877
878 dsdt.WriteString(`
Angel Ponsca623342019-01-16 21:55:55 +0100879 Device (\_SB.PCI0)
880 {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200881`)
882 for _, x := range DSDTPCI0Includes {
883 if x.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100884 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200885 }
886 fmt.Fprintf(dsdt, "\t\t#include <%s>\n", x.File)
887 }
888 dsdt.WriteString(
Angel Ponsca623342019-01-16 21:55:55 +0100889 ` }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200890}
891`)
892
Iru Caicd980ab2019-01-14 20:38:16 +0800893 if IGDEnabled {
894 gma := Create(ctx, "gma-mainboard.ads")
895 defer gma.Close()
896
897 gma.WriteString(`--
898-- This file is part of the coreboot project.
899--
900-- This program is free software; you can redistribute it and/or modify
901-- it under the terms of the GNU General Public License as published by
902-- the Free Software Foundation; either version 2 of the License, or
903-- (at your option) any later version.
904--
905-- This program is distributed in the hope that it will be useful,
906-- but WITHOUT ANY WARRANTY; without even the implied warranty of
907-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
908-- GNU General Public License for more details.
909--
910
911with HW.GFX.GMA;
912with HW.GFX.GMA.Display_Probing;
913
914use HW.GFX.GMA;
915use HW.GFX.GMA.Display_Probing;
916
917private package GMA.Mainboard is
918
919 -- FIXME: check this
920 ports : constant Port_List :=
921 (DP1,
922 DP2,
923 DP3,
924 HDMI1,
925 HDMI2,
926 HDMI3,
927 Analog,
928 Internal,
929 others => Disabled);
930
931end GMA.Mainboard;
932`)
933 }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200934}