blob: e3c3fdfa062a7af13b102aeda3b4338225025484 [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
Arthur Heymans59302852017-05-01 10:33:56 +0200215func Add_gpl(fp *os.File) {
216 fp.WriteString(`/*
217 * This file is part of the coreboot project.
218 *
219 * Copyright (C) 2008-2009 coresystems GmbH
220 * Copyright (C) 2014 Vladimir Serbinenko
221 *
222 * This program is free software; you can redistribute it and/or
223 * modify it under the terms of the GNU General Public License as
224 * published by the Free Software Foundation; version 2 of
225 * the License.
226 *
227 * This program is distributed in the hope that it will be useful,
228 * but WITHOUT ANY WARRANTY; without even the implied warranty of
229 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
230 * GNU General Public License for more details.
231 */
232
233`)
234}
235
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200236func RestorePCI16Simple(f *os.File, pcidev PCIDevData, addr uint16) {
237 fmt.Fprintf(f, " pci_write_config16(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x);\n",
238 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
239 pcidev.ConfigDump[addr+1],
240 pcidev.ConfigDump[addr])
241}
242
243func RestorePCI32Simple(f *os.File, pcidev PCIDevData, addr uint16) {
244 fmt.Fprintf(f, " pci_write_config32(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x%02x%02x);\n",
245 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
246 pcidev.ConfigDump[addr+3],
247 pcidev.ConfigDump[addr+2],
248 pcidev.ConfigDump[addr+1],
249 pcidev.ConfigDump[addr])
250}
251
252func RestoreRCBA32(f *os.File, inteltool InteltoolData, addr uint16) {
253 fmt.Fprintf(f, "\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr])
254}
255
256type PCISlot struct {
257 PCIAddr
258 additionalComment string
259 writeEmpty bool
260}
261
262type DevTreeNode struct {
263 Bus int
264 Dev int
265 Func int
266 Disabled bool
267 Registers map[string]string
268 IOs map[uint16]uint16
269 Children []DevTreeNode
270 PCISlots []PCISlot
271 PCIController bool
272 ChildPCIBus int
273 MissingParent string
274 SubVendor uint16
275 SubSystem uint16
276 Chip string
277 Comment string
278}
279
280var DevTree DevTreeNode
281var MissingChildren map[string][]DevTreeNode = map[string][]DevTreeNode{}
282var unmatchedPCIChips map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
283var unmatchedPCIDevices map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
284
285func Offset(dt *os.File, offset int) {
286 for i := 0; i < offset; i++ {
287 fmt.Fprintf(dt, "\t")
288 }
289}
290
291func MatchDev(dev *DevTreeNode) {
292 for idx := range dev.Children {
293 MatchDev(&dev.Children[idx])
294 }
295
296 for _, slot := range dev.PCISlots {
297 slotChip, ok := unmatchedPCIChips[slot.PCIAddr]
298
299 if !ok {
300 continue
301 }
302
303 if slot.additionalComment != "" && slotChip.Comment != "" {
304 slotChip.Comment = slot.additionalComment + " " + slotChip.Comment
305 } else {
306 slotChip.Comment = slot.additionalComment + slotChip.Comment
307 }
308
309 delete(unmatchedPCIChips, slot.PCIAddr)
310 MatchDev(&slotChip)
311 dev.Children = append(dev.Children, slotChip)
312 }
313
314 if dev.PCIController {
315 for slot, slotDev := range unmatchedPCIChips {
316 if slot.Bus == dev.ChildPCIBus {
317 delete(unmatchedPCIChips, slot)
318 MatchDev(&slotDev)
319 dev.Children = append(dev.Children, slotDev)
320 }
321 }
322 }
323
324 for _, slot := range dev.PCISlots {
325 slotDev, ok := unmatchedPCIDevices[slot.PCIAddr]
326 if !ok {
327 if slot.writeEmpty {
328 dev.Children = append(dev.Children,
329 DevTreeNode{
330 Registers: map[string]string{},
331 Chip: "pci",
332 Bus: slot.Bus,
333 Dev: slot.Dev,
334 Func: slot.Func,
335 Comment: slot.additionalComment,
336 Disabled: true,
337 },
338 )
339 }
340 continue
341 }
342
343 if slot.additionalComment != "" && slotDev.Comment != "" {
344 slotDev.Comment = slot.additionalComment + " " + slotDev.Comment
345 } else {
346 slotDev.Comment = slot.additionalComment + slotDev.Comment
347 }
348
349 MatchDev(&slotDev)
350 dev.Children = append(dev.Children, slotDev)
351 delete(unmatchedPCIDevices, slot.PCIAddr)
352 }
353
354 if dev.MissingParent != "" {
355 for _, child := range MissingChildren[dev.MissingParent] {
356 MatchDev(&child)
357 dev.Children = append(dev.Children, child)
358 }
359 delete(MissingChildren, dev.MissingParent)
360 }
361
362 if dev.PCIController {
363 for slot, slotDev := range unmatchedPCIDevices {
364 if slot.Bus == dev.ChildPCIBus {
365 MatchDev(&slotDev)
366 dev.Children = append(dev.Children, slotDev)
367 delete(unmatchedPCIDevices, slot)
368 }
369 }
370 }
371}
372
373func writeOn(dt *os.File, dev DevTreeNode) {
374 if dev.Disabled {
375 fmt.Fprintf(dt, "off")
376 } else {
377 fmt.Fprintf(dt, "on")
378 }
379}
380
381func WriteDev(dt *os.File, offset int, dev DevTreeNode) {
382 Offset(dt, offset)
383 switch dev.Chip {
384 case "cpu_cluster", "lapic", "domain", "ioapic":
385 fmt.Fprintf(dt, "device %s 0x%x ", dev.Chip, dev.Dev)
386 writeOn(dt, dev)
387 case "pci", "pnp":
388 fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func)
389 writeOn(dt, dev)
390 case "i2c":
391 fmt.Fprintf(dt, "device %s %02x ", dev.Chip, dev.Dev)
392 writeOn(dt, dev)
393 default:
394 fmt.Fprintf(dt, "chip %s", dev.Chip)
395 }
396 if dev.Comment != "" {
397 fmt.Fprintf(dt, " # %s", dev.Comment)
398 }
399 fmt.Fprintf(dt, "\n")
400 if dev.Chip == "pci" && dev.SubSystem != 0 && dev.SubVendor != 0 {
401 Offset(dt, offset+1)
402 fmt.Fprintf(dt, "subsystemid 0x%04x 0x%04x\n", dev.SubVendor, dev.SubSystem)
403 }
404
405 ioapic, ok := IOAPICIRQs[PCIAddr{Bus: dev.Bus, Dev: dev.Dev, Func: dev.Func}]
406 if dev.Chip == "pci" && ok {
407 for pin, irq := range ioapic.IRQNO {
408 if irq != 0 {
409 Offset(dt, offset+1)
410 fmt.Fprintf(dt, "ioapic_irq %d INT%c 0x%x\n", ioapic.APICID, 'A'+pin, irq)
411 }
412 }
413 }
414
415 keys := []string{}
416 for reg, _ := range dev.Registers {
417 keys = append(keys, reg)
418 }
419
420 sort.Strings(keys)
421
422 for _, reg := range keys {
423 val := dev.Registers[reg]
424 Offset(dt, offset+1)
425 fmt.Fprintf(dt, "register \"%s\" = \"%s\"\n", reg, val)
426 }
427
428 ios := []int{}
429 for reg, _ := range dev.IOs {
430 ios = append(ios, int(reg))
431 }
432
433 sort.Ints(ios)
434
435 for _, reg := range ios {
436 val := dev.IOs[uint16(reg)]
437 Offset(dt, offset+1)
438 fmt.Fprintf(dt, "io 0x%x = 0x%x\n", reg, val)
439 }
440
441 for _, child := range dev.Children {
442 WriteDev(dt, offset+1, child)
443 }
444
445 Offset(dt, offset)
446 fmt.Fprintf(dt, "end\n")
447}
448
449func PutChip(domain string, cur DevTreeNode) {
450 MissingChildren[domain] = append(MissingChildren[domain], cur)
451}
452
453func PutPCIChip(addr PCIDevData, cur DevTreeNode) {
454 unmatchedPCIChips[addr.PCIAddr] = cur
455}
456
457func PutPCIDevParent(addr PCIDevData, comment string, parent string) {
458 cur := DevTreeNode{
459 Registers: map[string]string{},
460 Chip: "pci",
461 Bus: addr.Bus,
462 Dev: addr.Dev,
463 Func: addr.Func,
464 MissingParent: parent,
465 Comment: comment,
466 }
467 if addr.ConfigDump[0xa] == 0x04 && addr.ConfigDump[0xb] == 0x06 {
468 cur.PCIController = true
469 cur.ChildPCIBus = int(addr.ConfigDump[0x19])
470
471 loopCtr := 0
472 for capPtr := addr.ConfigDump[0x34]; capPtr != 0; capPtr = addr.ConfigDump[capPtr+1] {
473 /* Avoid hangs. There are only 0x100 different possible values for capPtr.
474 If we iterate longer than that, we're in endless loop. */
475 loopCtr++
476 if loopCtr > 0x100 {
477 break
478 }
479 if addr.ConfigDump[capPtr] == 0x0d {
480 cur.SubVendor = GetLE16(addr.ConfigDump[capPtr+4 : capPtr+6])
481 cur.SubSystem = GetLE16(addr.ConfigDump[capPtr+6 : capPtr+8])
482 }
483 }
484 } else {
485 cur.SubVendor = GetLE16(addr.ConfigDump[0x2c:0x2e])
486 cur.SubSystem = GetLE16(addr.ConfigDump[0x2e:0x30])
487 }
488 unmatchedPCIDevices[addr.PCIAddr] = cur
489}
490
491func PutPCIDev(addr PCIDevData, comment string) {
492 PutPCIDevParent(addr, comment, "")
493}
494
495type GenericPCI struct {
496 Comment string
497 Bus0Subdiv string
498 MissingParent string
499}
500
501type GenericVGA struct {
502 GenericPCI
503}
504
505type DSDTInclude struct {
506 Comment string
507 File string
508}
509
510type DSDTDefine struct {
511 Key string
512 Comment string
513 Value string
514}
515
516var DSDTIncludes []DSDTInclude
517var DSDTPCI0Includes []DSDTInclude
518var DSDTDefines []DSDTDefine
519
520func (g GenericPCI) Scan(ctx Context, addr PCIDevData) {
521 PutPCIDevParent(addr, g.Comment, g.MissingParent)
522}
523
Iru Caicd980ab2019-01-14 20:38:16 +0800524var IGDEnabled bool = false
525
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200526func (g GenericVGA) Scan(ctx Context, addr PCIDevData) {
527 KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x",
528 addr.PCIVenID,
529 addr.PCIDevID)
530 KconfigString["VGA_BIOS_FILE"] = fmt.Sprintf("pci%04x,%04x.rom",
531 addr.PCIVenID,
532 addr.PCIDevID)
533 PutPCIDevParent(addr, g.Comment, g.MissingParent)
Iru Caicd980ab2019-01-14 20:38:16 +0800534 IGDEnabled = true
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200535}
536
537func makeKconfigName(ctx Context) {
538 kn := Create(ctx, "Kconfig.name")
539 defer kn.Close()
540
541 fmt.Fprintf(kn, "config %s\n\tbool \"%s\"\n", ctx.KconfigName, ctx.Model)
542}
543
544func makeComment(name string) string {
545 cmt, ok := KconfigComment[name]
546 if !ok {
547 return ""
548 }
549 return " # " + cmt
550}
551
552func makeKconfig(ctx Context) {
553 kc := Create(ctx, "Kconfig")
554 defer kc.Close()
555
556 fmt.Fprintf(kc, "if %s\n\n", ctx.KconfigName)
557
Elyes HAOUASf0c5be22018-11-27 20:36:44 +0100558 fmt.Fprintf(kc, "config BOARD_SPECIFIC_OPTIONS\n\tdef_bool y\n")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200559 keys := []string{}
560 for name, val := range KconfigBool {
561 if val {
562 keys = append(keys, name)
563 }
564 }
565
566 sort.Strings(keys)
567
568 for _, name := range keys {
569 fmt.Fprintf(kc, "\tselect %s%s\n", name, makeComment(name))
570 }
571
572 keys = nil
573 for name, val := range KconfigBool {
574 if !val {
575 keys = append(keys, name)
576 }
577 }
578
579 sort.Strings(keys)
580
581 for _, name := range keys {
582 fmt.Fprintf(kc, `
583config %s%s
584 bool
585 default n
586`, name, makeComment(name))
587 }
588
589 keys = nil
590 for name, _ := range KconfigStringUnquoted {
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), KconfigStringUnquoted[name])
602 }
603
604 keys = nil
605 for name, _ := range KconfigString {
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 string
615 default "%s"
616`, name, makeComment(name), KconfigString[name])
617 }
618
619 keys = nil
620 for name, _ := range KconfigHex {
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 hex
630 default 0x%x
631`, name, makeComment(name), KconfigHex[name])
632 }
633
634 keys = nil
635 for name, _ := range KconfigInt {
636 keys = append(keys, name)
637 }
638
639 sort.Strings(keys)
640
641 for _, name := range keys {
642 fmt.Fprintf(kc, `
643config %s%s
644 int
645 default %d
646`, name, makeComment(name), KconfigInt[name])
647 }
648
649 fmt.Fprintf(kc, "endif\n")
650}
651
652const MoboDir = "/src/mainboard/"
653
654func makeVendor(ctx Context) {
655 vendor := ctx.Vendor
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200656 vendorSane := ctx.SaneVendor
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200657 vendorDir := *FlagOutDir + MoboDir + vendorSane
658 vendorUpper := strings.ToUpper(vendorSane)
659 kconfig := vendorDir + "/Kconfig"
660 if _, err := os.Stat(kconfig); os.IsNotExist(err) {
661 f, err := os.Create(kconfig)
662 if err != nil {
663 log.Fatal(err)
664 }
665 defer f.Close()
666 f.WriteString(`if VENDOR_` + vendorUpper + `
667
668choice
669 prompt "Mainboard model"
670
671source "src/mainboard/` + vendorSane + `/*/Kconfig.name"
672
673endchoice
674
675source "src/mainboard/` + vendorSane + `/*/Kconfig"
676
677config MAINBOARD_VENDOR
678 string
679 default "` + vendor + `"
680
681endif # VENDOR_` + vendorUpper + "\n")
682 }
683 kconfigName := vendorDir + "/Kconfig.name"
684 if _, err := os.Stat(kconfigName); os.IsNotExist(err) {
685 f, err := os.Create(kconfigName)
686 if err != nil {
687 log.Fatal(err)
688 }
689 defer f.Close()
690 f.WriteString(`config VENDOR_` + vendorUpper + `
691 bool "` + vendor + `"
692`)
693 }
694
695}
696
697func GuessECGPE(ctx Context) int {
698 /* FIXME:XX Use iasl -d and/or better parsing */
699 dsdt := ctx.InfoSource.GetACPI()["DSDT"]
700 idx := bytes.Index(dsdt, []byte{0x08, '_', 'G', 'P', 'E', 0x0a}) /* Name (_GPE, byte). */
701 if idx > 0 {
702 return int(dsdt[idx+6])
703 }
704 return -1
705}
706
707func GuessSPDMap(ctx Context) []uint8 {
708 dmi := ctx.InfoSource.GetDMI()
709
710 if dmi.Vendor == "LENOVO" {
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200711 return []uint8{0x50, 0x52, 0x51, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200712 }
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200713 return []uint8{0x50, 0x51, 0x52, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200714}
715
716func main() {
717 flag.Parse()
718
719 ctx := Context{}
720
721 ctx.InfoSource = MakeLogReader()
722
723 dmi := ctx.InfoSource.GetDMI()
724
725 ctx.Vendor = dmi.Vendor
726
727 if dmi.Vendor == "LENOVO" {
728 ctx.Model = dmi.Version
729 } else {
730 ctx.Model = dmi.Model
731 }
732
733 if dmi.IsLaptop {
734 KconfigBool["SYSTEM_TYPE_LAPTOP"] = true
735 }
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200736 ctx.SaneVendor = sanitize(ctx.Vendor)
737 for {
738 last := ctx.SaneVendor
739 for _, suf := range []string{"_inc", "_co", "_corp"} {
740 ctx.SaneVendor = strings.TrimSuffix(ctx.SaneVendor, suf)
741 }
742 if last == ctx.SaneVendor {
743 break
744 }
745 }
746 ctx.MoboID = ctx.SaneVendor + "/" + sanitize(ctx.Model)
747 ctx.KconfigName = "BOARD_" + strings.ToUpper(ctx.SaneVendor+"_"+sanitize(ctx.Model))
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200748 ctx.BaseDirectory = *FlagOutDir + MoboDir + ctx.MoboID
749 KconfigStringUnquoted["MAINBOARD_DIR"] = ctx.MoboID
750 KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model
751
752 os.MkdirAll(ctx.BaseDirectory, 0700)
753
754 makeVendor(ctx)
755
756 ScanRoot(ctx)
757
Iru Caicd980ab2019-01-14 20:38:16 +0800758 if IGDEnabled {
759 KconfigBool["MAINBOARD_HAS_LIBGFXINIT"] = true
760 KconfigComment["MAINBOARD_HAS_LIBGFXINIT"] = "FIXME: check this"
761 AddRAMStageFile("gma-mainboard.ads", "CONFIG_MAINBOARD_USE_LIBGFXINIT")
762 }
763
Angel Pons6779d232020-01-08 15:05:56 +0100764 if len(BootBlockFiles) > 0 || len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200765 mf := Create(ctx, "Makefile.inc")
766 defer mf.Close()
Angel Pons6779d232020-01-08 15:05:56 +0100767 writeMF(mf, BootBlockFiles, "bootblock")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200768 writeMF(mf, ROMStageFiles, "romstage")
769 writeMF(mf, RAMStageFiles, "ramstage")
770 writeMF(mf, SMMFiles, "smm")
771 }
772
773 devtree := Create(ctx, "devicetree.cb")
774 defer devtree.Close()
775
776 MatchDev(&DevTree)
777 WriteDev(devtree, 0, DevTree)
778
779 if MainboardInit != "" || MainboardEnable != "" || MainboardIncludes != nil {
780 mainboard := Create(ctx, "mainboard.c")
781 defer mainboard.Close()
782 mainboard.WriteString("#include <device/device.h>\n")
783 for _, include := range MainboardIncludes {
784 mainboard.WriteString("#include <" + include + ">\n")
785 }
786 mainboard.WriteString("\n")
787 if MainboardInit != "" {
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200788 mainboard.WriteString(`static void mainboard_init(struct device *dev)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200789{
790` + MainboardInit + "}\n\n")
791 }
792 if MainboardInit != "" || MainboardEnable != "" {
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200793 mainboard.WriteString("static void mainboard_enable(struct device *dev)\n{\n")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200794 if MainboardInit != "" {
795 mainboard.WriteString("\tdev->ops->init = mainboard_init;\n\n")
796 }
797 mainboard.WriteString(MainboardEnable)
798 mainboard.WriteString("}\n\n")
799 mainboard.WriteString(`struct chip_operations mainboard_ops = {
800 .enable_dev = mainboard_enable,
801};
802`)
803 }
804 }
805
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200806 bi := Create(ctx, "board_info.txt")
807 defer bi.Close()
808
809 fixme := ""
810
811 if dmi.IsLaptop {
812 bi.WriteString("Category: laptop\n")
813 } else {
814 bi.WriteString("Category: desktop\n")
815 fixme += "check category, "
816 }
817
818 missing := "ROM package, ROM socketed"
819
820 if ROMProtocol != "" {
821 fmt.Fprintf(bi, "ROM protocol: %s\n", ROMProtocol)
822 } else {
823 missing += ", ROM protocol"
824 }
825
826 if FlashROMSupport != "" {
827 fmt.Fprintf(bi, "Flashrom support: %s\n", FlashROMSupport)
828 } else {
829 missing += ", Flashrom support"
830 }
831
832 missing += ", Release year"
833
834 if fixme != "" {
835 fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing)
836 } else {
837 fmt.Fprintf(bi, "FIXME: put %s\n", missing)
838 }
839
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200840 if ROMSizeKB == 0 {
841 KconfigBool["BOARD_ROMSIZE_KB_2048"] = true
842 KconfigComment["BOARD_ROMSIZE_KB_2048"] = "FIXME: correct this"
843 } else {
844 KconfigBool[fmt.Sprintf("BOARD_ROMSIZE_KB_%d", ROMSizeKB)] = true
845 }
846
847 makeKconfig(ctx)
848 makeKconfigName(ctx)
849
850 dsdt := Create(ctx, "dsdt.asl")
851 defer dsdt.Close()
852
853 for _, define := range DSDTDefines {
854 if define.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100855 fmt.Fprintf(dsdt, "\t/* %s. */\n", define.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200856 }
857 dsdt.WriteString("#define " + define.Key + " " + define.Value + "\n")
858 }
859
860 dsdt.WriteString(
Angel Ponsca623342019-01-16 21:55:55 +0100861 `
Angel Pons6779d232020-01-08 15:05:56 +0100862
Angel Ponsca623342019-01-16 21:55:55 +0100863#include <arch/acpi.h>
Angel Pons6779d232020-01-08 15:05:56 +0100864
Elyes HAOUAS6d19a202018-11-22 11:15:29 +0100865DefinitionBlock(
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200866 "dsdt.aml",
867 "DSDT",
Angel Pons6779d232020-01-08 15:05:56 +0100868 0x02, /* DSDT revision: ACPI 2.0 and up */
Elyes HAOUAS6d19a202018-11-22 11:15:29 +0100869 OEM_ID,
870 ACPI_TABLE_CREATOR,
Angel Pons6779d232020-01-08 15:05:56 +0100871 0x20141018 /* OEM revision */
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200872)
873{
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200874 #include "acpi/platform.asl"
875`)
876
877 for _, x := range DSDTIncludes {
878 if x.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100879 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200880 }
881 fmt.Fprintf(dsdt, "\t#include <%s>\n", x.File)
882 }
883
884 dsdt.WriteString(`
Angel Ponsca623342019-01-16 21:55:55 +0100885 Device (\_SB.PCI0)
886 {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200887`)
888 for _, x := range DSDTPCI0Includes {
889 if x.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100890 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200891 }
892 fmt.Fprintf(dsdt, "\t\t#include <%s>\n", x.File)
893 }
894 dsdt.WriteString(
Angel Ponsca623342019-01-16 21:55:55 +0100895 ` }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200896}
897`)
898
Iru Caicd980ab2019-01-14 20:38:16 +0800899 if IGDEnabled {
900 gma := Create(ctx, "gma-mainboard.ads")
901 defer gma.Close()
902
903 gma.WriteString(`--
904-- This file is part of the coreboot project.
905--
906-- This program is free software; you can redistribute it and/or modify
907-- it under the terms of the GNU General Public License as published by
908-- the Free Software Foundation; either version 2 of the License, or
909-- (at your option) any later version.
910--
911-- This program is distributed in the hope that it will be useful,
912-- but WITHOUT ANY WARRANTY; without even the implied warranty of
913-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
914-- GNU General Public License for more details.
915--
916
917with HW.GFX.GMA;
918with HW.GFX.GMA.Display_Probing;
919
920use HW.GFX.GMA;
921use HW.GFX.GMA.Display_Probing;
922
923private package GMA.Mainboard is
924
925 -- FIXME: check this
926 ports : constant Port_List :=
927 (DP1,
928 DP2,
929 DP3,
930 HDMI1,
931 HDMI2,
932 HDMI3,
933 Analog,
Nico Huber4ce52902020-02-15 17:56:01 +0100934 LVDS,
935 eDP);
Iru Caicd980ab2019-01-14 20:38:16 +0800936
937end GMA.Mainboard;
938`)
939 }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200940}