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