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