blob: 99099d51f65715c8242f24bb4f5e833f2e43ac7b [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{}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200107var 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
Angel Pons6779d232020-01-08 15:05:56 +0100157func AddBootBlockFile(Name string, Condition string) {
158 BootBlockFiles[Name] = Condition
159}
160
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200161func AddROMStageFile(Name string, Condition string) {
162 ROMStageFiles[Name] = Condition
163}
164
165func AddRAMStageFile(Name string, Condition string) {
166 RAMStageFiles[Name] = Condition
167}
168
169func AddSMMFile(Name string, Condition string) {
170 SMMFiles[Name] = Condition
171}
172
173func IsIOPortUsedBy(ctx Context, port uint16, name string) bool {
174 for _, io := range ctx.InfoSource.GetIOPorts() {
175 if io.Start <= port && port <= io.End && io.Usage == name {
176 return true
177 }
178 }
179 return false
180}
181
182var FlagOutDir = flag.String("coreboot_dir", ".", "Resulting coreboot directory")
183
184func writeMF(mf *os.File, files map[string]string, category string) {
185 keys := []string{}
186 for file, _ := range files {
187 keys = append(keys, file)
188 }
189
190 sort.Strings(keys)
191
192 for _, file := range keys {
193 condition := files[file]
194 if condition == "" {
195 fmt.Fprintf(mf, "%s-y += %s\n", category, file)
196 } else {
Angel Pons6779d232020-01-08 15:05:56 +0100197 fmt.Fprintf(mf, "%s-$(%s) += %s\n", category, condition, file)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200198 }
199 }
200}
201
202func Create(ctx Context, name string) *os.File {
203 li := strings.LastIndex(name, "/")
204 if li > 0 {
205 os.MkdirAll(ctx.BaseDirectory+"/"+name[0:li], 0700)
206 }
207 mf, err := os.Create(ctx.BaseDirectory + "/" + name)
208 if err != nil {
209 log.Fatal(err)
210 }
211 return mf
212}
213
Angel Pons3d5d6e82020-03-18 23:55:36 +0100214func Add_gpl(f *os.File) {
215 fmt.Fprintln(f, "/* SPDX-License-Identifier: GPL-2.0-only */")
Angel Pons3d5d6e82020-03-18 23:55:36 +0100216 fmt.Fprintln(f)
Arthur Heymans59302852017-05-01 10:33:56 +0200217}
218
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200219func RestorePCI16Simple(f *os.File, pcidev PCIDevData, addr uint16) {
220 fmt.Fprintf(f, " pci_write_config16(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x);\n",
221 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
222 pcidev.ConfigDump[addr+1],
223 pcidev.ConfigDump[addr])
224}
225
226func RestorePCI32Simple(f *os.File, pcidev PCIDevData, addr uint16) {
227 fmt.Fprintf(f, " pci_write_config32(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x%02x%02x);\n",
228 pcidev.Bus, pcidev.Dev, pcidev.Func, addr,
229 pcidev.ConfigDump[addr+3],
230 pcidev.ConfigDump[addr+2],
231 pcidev.ConfigDump[addr+1],
232 pcidev.ConfigDump[addr])
233}
234
235func RestoreRCBA32(f *os.File, inteltool InteltoolData, addr uint16) {
236 fmt.Fprintf(f, "\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr])
237}
238
239type PCISlot struct {
240 PCIAddr
Arthur Heymansbc3261f2023-01-30 13:32:44 +0100241 alias string
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200242 additionalComment string
243 writeEmpty bool
244}
245
246type DevTreeNode struct {
247 Bus int
248 Dev int
249 Func int
250 Disabled bool
251 Registers map[string]string
252 IOs map[uint16]uint16
253 Children []DevTreeNode
254 PCISlots []PCISlot
255 PCIController bool
256 ChildPCIBus int
257 MissingParent string
258 SubVendor uint16
259 SubSystem uint16
260 Chip string
261 Comment string
262}
263
264var DevTree DevTreeNode
265var MissingChildren map[string][]DevTreeNode = map[string][]DevTreeNode{}
266var unmatchedPCIChips map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
267var unmatchedPCIDevices map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{}
268
269func Offset(dt *os.File, offset int) {
270 for i := 0; i < offset; i++ {
271 fmt.Fprintf(dt, "\t")
272 }
273}
274
275func MatchDev(dev *DevTreeNode) {
276 for idx := range dev.Children {
277 MatchDev(&dev.Children[idx])
278 }
279
280 for _, slot := range dev.PCISlots {
281 slotChip, ok := unmatchedPCIChips[slot.PCIAddr]
282
283 if !ok {
284 continue
285 }
286
287 if slot.additionalComment != "" && slotChip.Comment != "" {
288 slotChip.Comment = slot.additionalComment + " " + slotChip.Comment
289 } else {
290 slotChip.Comment = slot.additionalComment + slotChip.Comment
291 }
292
293 delete(unmatchedPCIChips, slot.PCIAddr)
294 MatchDev(&slotChip)
295 dev.Children = append(dev.Children, slotChip)
296 }
297
298 if dev.PCIController {
299 for slot, slotDev := range unmatchedPCIChips {
300 if slot.Bus == dev.ChildPCIBus {
301 delete(unmatchedPCIChips, slot)
302 MatchDev(&slotDev)
303 dev.Children = append(dev.Children, slotDev)
304 }
305 }
306 }
307
308 for _, slot := range dev.PCISlots {
309 slotDev, ok := unmatchedPCIDevices[slot.PCIAddr]
310 if !ok {
311 if slot.writeEmpty {
312 dev.Children = append(dev.Children,
313 DevTreeNode{
314 Registers: map[string]string{},
315 Chip: "pci",
316 Bus: slot.Bus,
317 Dev: slot.Dev,
318 Func: slot.Func,
319 Comment: slot.additionalComment,
320 Disabled: true,
321 },
322 )
323 }
324 continue
325 }
326
327 if slot.additionalComment != "" && slotDev.Comment != "" {
328 slotDev.Comment = slot.additionalComment + " " + slotDev.Comment
329 } else {
330 slotDev.Comment = slot.additionalComment + slotDev.Comment
331 }
332
333 MatchDev(&slotDev)
334 dev.Children = append(dev.Children, slotDev)
335 delete(unmatchedPCIDevices, slot.PCIAddr)
336 }
337
338 if dev.MissingParent != "" {
339 for _, child := range MissingChildren[dev.MissingParent] {
340 MatchDev(&child)
341 dev.Children = append(dev.Children, child)
342 }
343 delete(MissingChildren, dev.MissingParent)
344 }
345
346 if dev.PCIController {
347 for slot, slotDev := range unmatchedPCIDevices {
348 if slot.Bus == dev.ChildPCIBus {
349 MatchDev(&slotDev)
350 dev.Children = append(dev.Children, slotDev)
351 delete(unmatchedPCIDevices, slot)
352 }
353 }
354 }
355}
356
357func writeOn(dt *os.File, dev DevTreeNode) {
358 if dev.Disabled {
359 fmt.Fprintf(dt, "off")
360 } else {
361 fmt.Fprintf(dt, "on")
362 }
363}
364
Arthur Heymansbc3261f2023-01-30 13:32:44 +0100365func WriteDev(dt *os.File, offset int, alias string, dev DevTreeNode) {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200366 Offset(dt, offset)
367 switch dev.Chip {
368 case "cpu_cluster", "lapic", "domain", "ioapic":
369 fmt.Fprintf(dt, "device %s 0x%x ", dev.Chip, dev.Dev)
370 writeOn(dt, dev)
371 case "pci", "pnp":
Arthur Heymansbc3261f2023-01-30 13:32:44 +0100372 if alias != "" {
373 fmt.Fprintf(dt, "device ref %s ", alias)
374 } else {
375 fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func)
376 }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200377 writeOn(dt, dev)
378 case "i2c":
379 fmt.Fprintf(dt, "device %s %02x ", dev.Chip, dev.Dev)
380 writeOn(dt, dev)
381 default:
382 fmt.Fprintf(dt, "chip %s", dev.Chip)
383 }
384 if dev.Comment != "" {
385 fmt.Fprintf(dt, " # %s", dev.Comment)
386 }
387 fmt.Fprintf(dt, "\n")
388 if dev.Chip == "pci" && dev.SubSystem != 0 && dev.SubVendor != 0 {
389 Offset(dt, offset+1)
390 fmt.Fprintf(dt, "subsystemid 0x%04x 0x%04x\n", dev.SubVendor, dev.SubSystem)
391 }
392
393 ioapic, ok := IOAPICIRQs[PCIAddr{Bus: dev.Bus, Dev: dev.Dev, Func: dev.Func}]
394 if dev.Chip == "pci" && ok {
395 for pin, irq := range ioapic.IRQNO {
396 if irq != 0 {
397 Offset(dt, offset+1)
398 fmt.Fprintf(dt, "ioapic_irq %d INT%c 0x%x\n", ioapic.APICID, 'A'+pin, irq)
399 }
400 }
401 }
402
403 keys := []string{}
404 for reg, _ := range dev.Registers {
405 keys = append(keys, reg)
406 }
407
408 sort.Strings(keys)
409
410 for _, reg := range keys {
411 val := dev.Registers[reg]
412 Offset(dt, offset+1)
413 fmt.Fprintf(dt, "register \"%s\" = \"%s\"\n", reg, val)
414 }
415
416 ios := []int{}
417 for reg, _ := range dev.IOs {
418 ios = append(ios, int(reg))
419 }
420
421 sort.Ints(ios)
422
423 for _, reg := range ios {
424 val := dev.IOs[uint16(reg)]
425 Offset(dt, offset+1)
426 fmt.Fprintf(dt, "io 0x%x = 0x%x\n", reg, val)
427 }
428
429 for _, child := range dev.Children {
Arthur Heymansbc3261f2023-01-30 13:32:44 +0100430 alias = ""
431 for _, slot := range dev.PCISlots {
432 if slot.PCIAddr.Bus == child.Bus &&
433 slot.PCIAddr.Dev == child.Dev && slot.PCIAddr.Func == child.Func {
434 alias = slot.alias
435 }
436 }
437 WriteDev(dt, offset+1, alias, child)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200438 }
439
440 Offset(dt, offset)
441 fmt.Fprintf(dt, "end\n")
442}
443
444func PutChip(domain string, cur DevTreeNode) {
445 MissingChildren[domain] = append(MissingChildren[domain], cur)
446}
447
448func PutPCIChip(addr PCIDevData, cur DevTreeNode) {
449 unmatchedPCIChips[addr.PCIAddr] = cur
450}
451
452func PutPCIDevParent(addr PCIDevData, comment string, parent string) {
453 cur := DevTreeNode{
454 Registers: map[string]string{},
455 Chip: "pci",
456 Bus: addr.Bus,
457 Dev: addr.Dev,
458 Func: addr.Func,
459 MissingParent: parent,
460 Comment: comment,
461 }
462 if addr.ConfigDump[0xa] == 0x04 && addr.ConfigDump[0xb] == 0x06 {
463 cur.PCIController = true
464 cur.ChildPCIBus = int(addr.ConfigDump[0x19])
465
466 loopCtr := 0
467 for capPtr := addr.ConfigDump[0x34]; capPtr != 0; capPtr = addr.ConfigDump[capPtr+1] {
468 /* Avoid hangs. There are only 0x100 different possible values for capPtr.
469 If we iterate longer than that, we're in endless loop. */
470 loopCtr++
471 if loopCtr > 0x100 {
472 break
473 }
474 if addr.ConfigDump[capPtr] == 0x0d {
475 cur.SubVendor = GetLE16(addr.ConfigDump[capPtr+4 : capPtr+6])
476 cur.SubSystem = GetLE16(addr.ConfigDump[capPtr+6 : capPtr+8])
477 }
478 }
479 } else {
480 cur.SubVendor = GetLE16(addr.ConfigDump[0x2c:0x2e])
481 cur.SubSystem = GetLE16(addr.ConfigDump[0x2e:0x30])
482 }
483 unmatchedPCIDevices[addr.PCIAddr] = cur
484}
485
486func PutPCIDev(addr PCIDevData, comment string) {
487 PutPCIDevParent(addr, comment, "")
488}
489
490type GenericPCI struct {
491 Comment string
492 Bus0Subdiv string
493 MissingParent string
494}
495
496type GenericVGA struct {
497 GenericPCI
498}
499
500type DSDTInclude struct {
501 Comment string
502 File string
503}
504
505type DSDTDefine struct {
506 Key string
507 Comment string
508 Value string
509}
510
511var DSDTIncludes []DSDTInclude
512var DSDTPCI0Includes []DSDTInclude
513var DSDTDefines []DSDTDefine
514
515func (g GenericPCI) Scan(ctx Context, addr PCIDevData) {
516 PutPCIDevParent(addr, g.Comment, g.MissingParent)
517}
518
Iru Caicd980ab2019-01-14 20:38:16 +0800519var IGDEnabled bool = false
520
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200521func (g GenericVGA) Scan(ctx Context, addr PCIDevData) {
522 KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x",
523 addr.PCIVenID,
524 addr.PCIDevID)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200525 PutPCIDevParent(addr, g.Comment, g.MissingParent)
Iru Caicd980ab2019-01-14 20:38:16 +0800526 IGDEnabled = true
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200527}
528
529func makeKconfigName(ctx Context) {
530 kn := Create(ctx, "Kconfig.name")
531 defer kn.Close()
532
533 fmt.Fprintf(kn, "config %s\n\tbool \"%s\"\n", ctx.KconfigName, ctx.Model)
534}
535
536func makeComment(name string) string {
537 cmt, ok := KconfigComment[name]
538 if !ok {
539 return ""
540 }
541 return " # " + cmt
542}
543
544func makeKconfig(ctx Context) {
545 kc := Create(ctx, "Kconfig")
546 defer kc.Close()
547
548 fmt.Fprintf(kc, "if %s\n\n", ctx.KconfigName)
549
Elyes HAOUASf0c5be22018-11-27 20:36:44 +0100550 fmt.Fprintf(kc, "config BOARD_SPECIFIC_OPTIONS\n\tdef_bool y\n")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200551 keys := []string{}
552 for name, val := range KconfigBool {
553 if val {
554 keys = append(keys, name)
555 }
556 }
557
558 sort.Strings(keys)
559
560 for _, name := range keys {
561 fmt.Fprintf(kc, "\tselect %s%s\n", name, makeComment(name))
562 }
563
564 keys = nil
565 for name, val := range KconfigBool {
566 if !val {
567 keys = append(keys, name)
568 }
569 }
570
571 sort.Strings(keys)
572
573 for _, name := range keys {
574 fmt.Fprintf(kc, `
575config %s%s
576 bool
577 default n
578`, name, makeComment(name))
579 }
580
581 keys = nil
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200582 for name, _ := range KconfigString {
583 keys = append(keys, name)
584 }
585
586 sort.Strings(keys)
587
588 for _, name := range keys {
589 fmt.Fprintf(kc, `
590config %s%s
591 string
592 default "%s"
593`, name, makeComment(name), KconfigString[name])
594 }
595
596 keys = nil
597 for name, _ := range KconfigHex {
598 keys = append(keys, name)
599 }
600
601 sort.Strings(keys)
602
603 for _, name := range keys {
604 fmt.Fprintf(kc, `
605config %s%s
606 hex
607 default 0x%x
608`, name, makeComment(name), KconfigHex[name])
609 }
610
611 keys = nil
612 for name, _ := range KconfigInt {
613 keys = append(keys, name)
614 }
615
616 sort.Strings(keys)
617
618 for _, name := range keys {
619 fmt.Fprintf(kc, `
620config %s%s
621 int
622 default %d
623`, name, makeComment(name), KconfigInt[name])
624 }
625
626 fmt.Fprintf(kc, "endif\n")
627}
628
629const MoboDir = "/src/mainboard/"
630
631func makeVendor(ctx Context) {
632 vendor := ctx.Vendor
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200633 vendorSane := ctx.SaneVendor
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200634 vendorDir := *FlagOutDir + MoboDir + vendorSane
635 vendorUpper := strings.ToUpper(vendorSane)
636 kconfig := vendorDir + "/Kconfig"
637 if _, err := os.Stat(kconfig); os.IsNotExist(err) {
638 f, err := os.Create(kconfig)
639 if err != nil {
640 log.Fatal(err)
641 }
642 defer f.Close()
643 f.WriteString(`if VENDOR_` + vendorUpper + `
644
645choice
646 prompt "Mainboard model"
647
648source "src/mainboard/` + vendorSane + `/*/Kconfig.name"
649
650endchoice
651
652source "src/mainboard/` + vendorSane + `/*/Kconfig"
653
654config MAINBOARD_VENDOR
655 string
656 default "` + vendor + `"
657
658endif # VENDOR_` + vendorUpper + "\n")
659 }
660 kconfigName := vendorDir + "/Kconfig.name"
661 if _, err := os.Stat(kconfigName); os.IsNotExist(err) {
662 f, err := os.Create(kconfigName)
663 if err != nil {
664 log.Fatal(err)
665 }
666 defer f.Close()
667 f.WriteString(`config VENDOR_` + vendorUpper + `
668 bool "` + vendor + `"
669`)
670 }
671
672}
673
674func GuessECGPE(ctx Context) int {
675 /* FIXME:XX Use iasl -d and/or better parsing */
676 dsdt := ctx.InfoSource.GetACPI()["DSDT"]
677 idx := bytes.Index(dsdt, []byte{0x08, '_', 'G', 'P', 'E', 0x0a}) /* Name (_GPE, byte). */
678 if idx > 0 {
679 return int(dsdt[idx+6])
680 }
681 return -1
682}
683
684func GuessSPDMap(ctx Context) []uint8 {
685 dmi := ctx.InfoSource.GetDMI()
686
687 if dmi.Vendor == "LENOVO" {
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200688 return []uint8{0x50, 0x52, 0x51, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200689 }
Vladimir Serbinenkodb0acf82015-05-29 22:09:06 +0200690 return []uint8{0x50, 0x51, 0x52, 0x53}
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200691}
692
693func main() {
694 flag.Parse()
695
696 ctx := Context{}
697
698 ctx.InfoSource = MakeLogReader()
699
700 dmi := ctx.InfoSource.GetDMI()
701
702 ctx.Vendor = dmi.Vendor
703
704 if dmi.Vendor == "LENOVO" {
705 ctx.Model = dmi.Version
706 } else {
707 ctx.Model = dmi.Model
708 }
709
710 if dmi.IsLaptop {
711 KconfigBool["SYSTEM_TYPE_LAPTOP"] = true
712 }
Vladimir Serbinenko2d615e52015-05-29 21:43:51 +0200713 ctx.SaneVendor = sanitize(ctx.Vendor)
714 for {
715 last := ctx.SaneVendor
716 for _, suf := range []string{"_inc", "_co", "_corp"} {
717 ctx.SaneVendor = strings.TrimSuffix(ctx.SaneVendor, suf)
718 }
719 if last == ctx.SaneVendor {
720 break
721 }
722 }
723 ctx.MoboID = ctx.SaneVendor + "/" + sanitize(ctx.Model)
724 ctx.KconfigName = "BOARD_" + strings.ToUpper(ctx.SaneVendor+"_"+sanitize(ctx.Model))
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200725 ctx.BaseDirectory = *FlagOutDir + MoboDir + ctx.MoboID
Iru Cai8c6d1612020-09-07 20:21:16 +0800726 KconfigString["MAINBOARD_DIR"] = ctx.MoboID
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200727 KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model
728
729 os.MkdirAll(ctx.BaseDirectory, 0700)
730
731 makeVendor(ctx)
732
733 ScanRoot(ctx)
734
Iru Caicd980ab2019-01-14 20:38:16 +0800735 if IGDEnabled {
736 KconfigBool["MAINBOARD_HAS_LIBGFXINIT"] = true
737 KconfigComment["MAINBOARD_HAS_LIBGFXINIT"] = "FIXME: check this"
738 AddRAMStageFile("gma-mainboard.ads", "CONFIG_MAINBOARD_USE_LIBGFXINIT")
739 }
740
Angel Pons6779d232020-01-08 15:05:56 +0100741 if len(BootBlockFiles) > 0 || len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 {
Martin Rothd0096c12024-01-18 19:17:36 -0700742 mf := Create(ctx, "Makefile.mk")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200743 defer mf.Close()
Angel Pons6779d232020-01-08 15:05:56 +0100744 writeMF(mf, BootBlockFiles, "bootblock")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200745 writeMF(mf, ROMStageFiles, "romstage")
746 writeMF(mf, RAMStageFiles, "ramstage")
747 writeMF(mf, SMMFiles, "smm")
748 }
749
750 devtree := Create(ctx, "devicetree.cb")
751 defer devtree.Close()
752
753 MatchDev(&DevTree)
Arthur Heymansbc3261f2023-01-30 13:32:44 +0100754 WriteDev(devtree, 0, "", DevTree)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200755
756 if MainboardInit != "" || MainboardEnable != "" || MainboardIncludes != nil {
757 mainboard := Create(ctx, "mainboard.c")
758 defer mainboard.Close()
Iru Cai16f213a2020-09-16 16:23:46 +0800759 Add_gpl(mainboard)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200760 mainboard.WriteString("#include <device/device.h>\n")
761 for _, include := range MainboardIncludes {
762 mainboard.WriteString("#include <" + include + ">\n")
763 }
764 mainboard.WriteString("\n")
765 if MainboardInit != "" {
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200766 mainboard.WriteString(`static void mainboard_init(struct device *dev)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200767{
768` + MainboardInit + "}\n\n")
769 }
770 if MainboardInit != "" || MainboardEnable != "" {
Elyes HAOUAS68c851b2018-06-12 22:06:09 +0200771 mainboard.WriteString("static void mainboard_enable(struct device *dev)\n{\n")
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200772 if MainboardInit != "" {
773 mainboard.WriteString("\tdev->ops->init = mainboard_init;\n\n")
774 }
775 mainboard.WriteString(MainboardEnable)
776 mainboard.WriteString("}\n\n")
777 mainboard.WriteString(`struct chip_operations mainboard_ops = {
778 .enable_dev = mainboard_enable,
779};
780`)
781 }
782 }
783
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200784 bi := Create(ctx, "board_info.txt")
785 defer bi.Close()
786
787 fixme := ""
788
789 if dmi.IsLaptop {
790 bi.WriteString("Category: laptop\n")
791 } else {
792 bi.WriteString("Category: desktop\n")
793 fixme += "check category, "
794 }
795
796 missing := "ROM package, ROM socketed"
797
798 if ROMProtocol != "" {
799 fmt.Fprintf(bi, "ROM protocol: %s\n", ROMProtocol)
800 } else {
801 missing += ", ROM protocol"
802 }
803
804 if FlashROMSupport != "" {
805 fmt.Fprintf(bi, "Flashrom support: %s\n", FlashROMSupport)
806 } else {
807 missing += ", Flashrom support"
808 }
809
810 missing += ", Release year"
811
812 if fixme != "" {
813 fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing)
814 } else {
815 fmt.Fprintf(bi, "FIXME: put %s\n", missing)
816 }
817
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200818 if ROMSizeKB == 0 {
819 KconfigBool["BOARD_ROMSIZE_KB_2048"] = true
820 KconfigComment["BOARD_ROMSIZE_KB_2048"] = "FIXME: correct this"
821 } else {
822 KconfigBool[fmt.Sprintf("BOARD_ROMSIZE_KB_%d", ROMSizeKB)] = true
823 }
824
825 makeKconfig(ctx)
826 makeKconfigName(ctx)
827
828 dsdt := Create(ctx, "dsdt.asl")
829 defer dsdt.Close()
830
831 for _, define := range DSDTDefines {
832 if define.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100833 fmt.Fprintf(dsdt, "\t/* %s. */\n", define.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200834 }
835 dsdt.WriteString("#define " + define.Key + " " + define.Value + "\n")
836 }
837
Iru Cai16f213a2020-09-16 16:23:46 +0800838 Add_gpl(dsdt)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200839 dsdt.WriteString(
Nicholas Chin7c05c612024-06-23 11:38:04 -0600840`#include <acpi/acpi.h>
Angel Pons6779d232020-01-08 15:05:56 +0100841
Elyes HAOUAS6d19a202018-11-22 11:15:29 +0100842DefinitionBlock(
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200843 "dsdt.aml",
844 "DSDT",
Elyes HAOUAS90d00de2020-10-05 16:38:53 +0200845 ACPI_DSDT_REV_2,
Elyes HAOUAS6d19a202018-11-22 11:15:29 +0100846 OEM_ID,
847 ACPI_TABLE_CREATOR,
Angel Ponsf1e40672024-05-13 20:11:36 +0200848 0x20141018
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200849)
850{
Kyösti Mälkki6215e612021-02-25 08:00:21 +0200851 #include <acpi/dsdt_top.asl>
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200852 #include "acpi/platform.asl"
853`)
854
855 for _, x := range DSDTIncludes {
856 if x.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100857 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200858 }
859 fmt.Fprintf(dsdt, "\t#include <%s>\n", x.File)
860 }
861
862 dsdt.WriteString(`
Angel Ponsca623342019-01-16 21:55:55 +0100863 Device (\_SB.PCI0)
864 {
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200865`)
866 for _, x := range DSDTPCI0Includes {
867 if x.Comment != "" {
Angel Ponsca623342019-01-16 21:55:55 +0100868 fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment)
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200869 }
870 fmt.Fprintf(dsdt, "\t\t#include <%s>\n", x.File)
871 }
872 dsdt.WriteString(
Angel Ponsca623342019-01-16 21:55:55 +0100873 ` }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200874}
875`)
876
Iru Caicd980ab2019-01-14 20:38:16 +0800877 if IGDEnabled {
878 gma := Create(ctx, "gma-mainboard.ads")
879 defer gma.Close()
880
Angel Pons3d5d6e82020-03-18 23:55:36 +0100881 gma.WriteString(`-- SPDX-License-Identifier: GPL-2.0-or-later
Iru Caicd980ab2019-01-14 20:38:16 +0800882
883with HW.GFX.GMA;
884with HW.GFX.GMA.Display_Probing;
885
886use HW.GFX.GMA;
887use HW.GFX.GMA.Display_Probing;
888
889private package GMA.Mainboard is
890
891 -- FIXME: check this
892 ports : constant Port_List :=
893 (DP1,
894 DP2,
895 DP3,
896 HDMI1,
897 HDMI2,
898 HDMI3,
899 Analog,
Nico Huber4ce52902020-02-15 17:56:01 +0100900 LVDS,
901 eDP);
Iru Caicd980ab2019-01-14 20:38:16 +0800902
903end GMA.Mainboard;
904`)
905 }
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200906}