| /* This is just an experiment. Full automatic porting |
| is probably not possible but a lot can be automated. */ |
| package main |
| |
| import ( |
| "bytes" |
| "flag" |
| "fmt" |
| "log" |
| "os" |
| "sort" |
| "strings" |
| ) |
| |
| type PCIAddr struct { |
| Bus int |
| Dev int |
| Func int |
| } |
| |
| type PCIDevData struct { |
| PCIAddr |
| PCIVenID uint16 |
| PCIDevID uint16 |
| ConfigDump []uint8 |
| } |
| |
| type PCIDevice interface { |
| Scan(ctx Context, addr PCIDevData) |
| } |
| |
| type InteltoolData struct { |
| GPIO map[uint16]uint32 |
| RCBA map[uint16]uint32 |
| IGD map[uint32]uint32 |
| } |
| |
| type DMIData struct { |
| Vendor string |
| Model string |
| Version string |
| IsLaptop bool |
| } |
| |
| type AzaliaCodec struct { |
| Name string |
| VendorID uint32 |
| SubsystemID uint32 |
| CodecNo int |
| PinConfig map[int]uint32 |
| } |
| |
| type DevReader interface { |
| GetPCIList() []PCIDevData |
| GetDMI() DMIData |
| GetInteltool() InteltoolData |
| GetAzaliaCodecs() []AzaliaCodec |
| GetACPI() map[string][]byte |
| GetCPUModel() []uint32 |
| GetEC() []byte |
| GetIOPorts() []IOPorts |
| } |
| |
| type IOPorts struct { |
| Start uint16 |
| End uint16 |
| Usage string |
| } |
| |
| type SouthBridger interface { |
| GetGPIOHeader() string |
| EncodeGPE(int) int |
| DecodeGPE(int) int |
| EnableGPE(int) |
| NeedRouteGPIOManually() |
| } |
| |
| var SouthBridge SouthBridger |
| var ROMStageFiles map[string]string = map[string]string{} |
| var RAMStageFiles map[string]string = map[string]string{} |
| var SMMFiles map[string]string = map[string]string{} |
| var MainboardInit string |
| var MainboardEnable string |
| var MainboardIncludes []string |
| |
| type Context struct { |
| MoboID string |
| KconfigName string |
| Vendor string |
| Model string |
| BaseDirectory string |
| InfoSource DevReader |
| SaneVendor string |
| } |
| |
| type IOAPICIRQ struct { |
| APICID int |
| IRQNO [4]int |
| } |
| |
| var IOAPICIRQs map[PCIAddr]IOAPICIRQ = map[PCIAddr]IOAPICIRQ{} |
| var KconfigBool map[string]bool = map[string]bool{} |
| var KconfigComment map[string]string = map[string]string{} |
| var KconfigString map[string]string = map[string]string{} |
| var KconfigStringUnquoted map[string]string = map[string]string{} |
| var KconfigHex map[string]uint32 = map[string]uint32{} |
| var KconfigInt map[string]int = map[string]int{} |
| var ROMSizeKB = 0 |
| var ROMProtocol = "" |
| var FlashROMSupport = "" |
| |
| func GetLE16(inp []byte) uint16 { |
| return uint16(inp[0]) | (uint16(inp[1]) << 8) |
| } |
| |
| func FormatHexLE16(inp []byte) string { |
| return fmt.Sprintf("0x%04x", GetLE16(inp)) |
| } |
| |
| func FormatHex32(u uint32) string { |
| return fmt.Sprintf("0x%08x", u) |
| } |
| |
| func FormatHex8(u uint8) string { |
| return fmt.Sprintf("0x%02x", u) |
| } |
| |
| func FormatInt32(u uint32) string { |
| return fmt.Sprintf("%d", u) |
| } |
| |
| func FormatHexLE32(d []uint8) string { |
| u := uint32(d[0]) | (uint32(d[1]) << 8) | (uint32(d[2]) << 16) | (uint32(d[3]) << 24) |
| return FormatHex32(u) |
| } |
| |
| func FormatBool(inp bool) string { |
| if inp { |
| return "1" |
| } else { |
| return "0" |
| } |
| } |
| |
| func sanitize(inp string) string { |
| result := strings.ToLower(inp) |
| result = strings.Replace(result, " ", "_", -1) |
| result = strings.Replace(result, ",", "_", -1) |
| for strings.HasSuffix(result, ".") { |
| result = result[0 : len(result)-1] |
| } |
| return result |
| } |
| |
| func AddROMStageFile(Name string, Condition string) { |
| ROMStageFiles[Name] = Condition |
| } |
| |
| func AddRAMStageFile(Name string, Condition string) { |
| RAMStageFiles[Name] = Condition |
| } |
| |
| func AddSMMFile(Name string, Condition string) { |
| SMMFiles[Name] = Condition |
| } |
| |
| func IsIOPortUsedBy(ctx Context, port uint16, name string) bool { |
| for _, io := range ctx.InfoSource.GetIOPorts() { |
| if io.Start <= port && port <= io.End && io.Usage == name { |
| return true |
| } |
| } |
| return false |
| } |
| |
| var FlagOutDir = flag.String("coreboot_dir", ".", "Resulting coreboot directory") |
| |
| func writeMF(mf *os.File, files map[string]string, category string) { |
| keys := []string{} |
| for file, _ := range files { |
| keys = append(keys, file) |
| } |
| |
| sort.Strings(keys) |
| |
| for _, file := range keys { |
| condition := files[file] |
| if condition == "" { |
| fmt.Fprintf(mf, "%s-y += %s\n", category, file) |
| } else { |
| fmt.Fprintf(mf, "%s-$(%s) += %s\n", category, |
| condition, file) |
| } |
| } |
| } |
| |
| func Create(ctx Context, name string) *os.File { |
| li := strings.LastIndex(name, "/") |
| if li > 0 { |
| os.MkdirAll(ctx.BaseDirectory+"/"+name[0:li], 0700) |
| } |
| mf, err := os.Create(ctx.BaseDirectory + "/" + name) |
| if err != nil { |
| log.Fatal(err) |
| } |
| return mf |
| } |
| |
| func RestorePCI16Simple(f *os.File, pcidev PCIDevData, addr uint16) { |
| fmt.Fprintf(f, " pci_write_config16(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x);\n", |
| pcidev.Bus, pcidev.Dev, pcidev.Func, addr, |
| pcidev.ConfigDump[addr+1], |
| pcidev.ConfigDump[addr]) |
| } |
| |
| func RestorePCI32Simple(f *os.File, pcidev PCIDevData, addr uint16) { |
| fmt.Fprintf(f, " pci_write_config32(PCI_DEV(%d, 0x%02x, %d), 0x%02x, 0x%02x%02x%02x%02x);\n", |
| pcidev.Bus, pcidev.Dev, pcidev.Func, addr, |
| pcidev.ConfigDump[addr+3], |
| pcidev.ConfigDump[addr+2], |
| pcidev.ConfigDump[addr+1], |
| pcidev.ConfigDump[addr]) |
| } |
| |
| func RestoreRCBA32(f *os.File, inteltool InteltoolData, addr uint16) { |
| fmt.Fprintf(f, "\tRCBA32(0x%04x) = 0x%08x;\n", addr, inteltool.RCBA[addr]) |
| } |
| |
| type PCISlot struct { |
| PCIAddr |
| additionalComment string |
| writeEmpty bool |
| } |
| |
| type DevTreeNode struct { |
| Bus int |
| Dev int |
| Func int |
| Disabled bool |
| Registers map[string]string |
| IOs map[uint16]uint16 |
| Children []DevTreeNode |
| PCISlots []PCISlot |
| PCIController bool |
| ChildPCIBus int |
| MissingParent string |
| SubVendor uint16 |
| SubSystem uint16 |
| Chip string |
| Comment string |
| } |
| |
| var DevTree DevTreeNode |
| var MissingChildren map[string][]DevTreeNode = map[string][]DevTreeNode{} |
| var unmatchedPCIChips map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{} |
| var unmatchedPCIDevices map[PCIAddr]DevTreeNode = map[PCIAddr]DevTreeNode{} |
| |
| func Offset(dt *os.File, offset int) { |
| for i := 0; i < offset; i++ { |
| fmt.Fprintf(dt, "\t") |
| } |
| } |
| |
| func MatchDev(dev *DevTreeNode) { |
| for idx := range dev.Children { |
| MatchDev(&dev.Children[idx]) |
| } |
| |
| for _, slot := range dev.PCISlots { |
| slotChip, ok := unmatchedPCIChips[slot.PCIAddr] |
| |
| if !ok { |
| continue |
| } |
| |
| if slot.additionalComment != "" && slotChip.Comment != "" { |
| slotChip.Comment = slot.additionalComment + " " + slotChip.Comment |
| } else { |
| slotChip.Comment = slot.additionalComment + slotChip.Comment |
| } |
| |
| delete(unmatchedPCIChips, slot.PCIAddr) |
| MatchDev(&slotChip) |
| dev.Children = append(dev.Children, slotChip) |
| } |
| |
| if dev.PCIController { |
| for slot, slotDev := range unmatchedPCIChips { |
| if slot.Bus == dev.ChildPCIBus { |
| delete(unmatchedPCIChips, slot) |
| MatchDev(&slotDev) |
| dev.Children = append(dev.Children, slotDev) |
| } |
| } |
| } |
| |
| for _, slot := range dev.PCISlots { |
| slotDev, ok := unmatchedPCIDevices[slot.PCIAddr] |
| if !ok { |
| if slot.writeEmpty { |
| dev.Children = append(dev.Children, |
| DevTreeNode{ |
| Registers: map[string]string{}, |
| Chip: "pci", |
| Bus: slot.Bus, |
| Dev: slot.Dev, |
| Func: slot.Func, |
| Comment: slot.additionalComment, |
| Disabled: true, |
| }, |
| ) |
| } |
| continue |
| } |
| |
| if slot.additionalComment != "" && slotDev.Comment != "" { |
| slotDev.Comment = slot.additionalComment + " " + slotDev.Comment |
| } else { |
| slotDev.Comment = slot.additionalComment + slotDev.Comment |
| } |
| |
| MatchDev(&slotDev) |
| dev.Children = append(dev.Children, slotDev) |
| delete(unmatchedPCIDevices, slot.PCIAddr) |
| } |
| |
| if dev.MissingParent != "" { |
| for _, child := range MissingChildren[dev.MissingParent] { |
| MatchDev(&child) |
| dev.Children = append(dev.Children, child) |
| } |
| delete(MissingChildren, dev.MissingParent) |
| } |
| |
| if dev.PCIController { |
| for slot, slotDev := range unmatchedPCIDevices { |
| if slot.Bus == dev.ChildPCIBus { |
| MatchDev(&slotDev) |
| dev.Children = append(dev.Children, slotDev) |
| delete(unmatchedPCIDevices, slot) |
| } |
| } |
| } |
| } |
| |
| func writeOn(dt *os.File, dev DevTreeNode) { |
| if dev.Disabled { |
| fmt.Fprintf(dt, "off") |
| } else { |
| fmt.Fprintf(dt, "on") |
| } |
| } |
| |
| func WriteDev(dt *os.File, offset int, dev DevTreeNode) { |
| Offset(dt, offset) |
| switch dev.Chip { |
| case "cpu_cluster", "lapic", "domain", "ioapic": |
| fmt.Fprintf(dt, "device %s 0x%x ", dev.Chip, dev.Dev) |
| writeOn(dt, dev) |
| case "pci", "pnp": |
| fmt.Fprintf(dt, "device %s %02x.%x ", dev.Chip, dev.Dev, dev.Func) |
| writeOn(dt, dev) |
| case "i2c": |
| fmt.Fprintf(dt, "device %s %02x ", dev.Chip, dev.Dev) |
| writeOn(dt, dev) |
| default: |
| fmt.Fprintf(dt, "chip %s", dev.Chip) |
| } |
| if dev.Comment != "" { |
| fmt.Fprintf(dt, " # %s", dev.Comment) |
| } |
| fmt.Fprintf(dt, "\n") |
| if dev.Chip == "pci" && dev.SubSystem != 0 && dev.SubVendor != 0 { |
| Offset(dt, offset+1) |
| fmt.Fprintf(dt, "subsystemid 0x%04x 0x%04x\n", dev.SubVendor, dev.SubSystem) |
| } |
| |
| ioapic, ok := IOAPICIRQs[PCIAddr{Bus: dev.Bus, Dev: dev.Dev, Func: dev.Func}] |
| if dev.Chip == "pci" && ok { |
| for pin, irq := range ioapic.IRQNO { |
| if irq != 0 { |
| Offset(dt, offset+1) |
| fmt.Fprintf(dt, "ioapic_irq %d INT%c 0x%x\n", ioapic.APICID, 'A'+pin, irq) |
| } |
| } |
| } |
| |
| keys := []string{} |
| for reg, _ := range dev.Registers { |
| keys = append(keys, reg) |
| } |
| |
| sort.Strings(keys) |
| |
| for _, reg := range keys { |
| val := dev.Registers[reg] |
| Offset(dt, offset+1) |
| fmt.Fprintf(dt, "register \"%s\" = \"%s\"\n", reg, val) |
| } |
| |
| ios := []int{} |
| for reg, _ := range dev.IOs { |
| ios = append(ios, int(reg)) |
| } |
| |
| sort.Ints(ios) |
| |
| for _, reg := range ios { |
| val := dev.IOs[uint16(reg)] |
| Offset(dt, offset+1) |
| fmt.Fprintf(dt, "io 0x%x = 0x%x\n", reg, val) |
| } |
| |
| for _, child := range dev.Children { |
| WriteDev(dt, offset+1, child) |
| } |
| |
| Offset(dt, offset) |
| fmt.Fprintf(dt, "end\n") |
| } |
| |
| func PutChip(domain string, cur DevTreeNode) { |
| MissingChildren[domain] = append(MissingChildren[domain], cur) |
| } |
| |
| func PutPCIChip(addr PCIDevData, cur DevTreeNode) { |
| unmatchedPCIChips[addr.PCIAddr] = cur |
| } |
| |
| func PutPCIDevParent(addr PCIDevData, comment string, parent string) { |
| cur := DevTreeNode{ |
| Registers: map[string]string{}, |
| Chip: "pci", |
| Bus: addr.Bus, |
| Dev: addr.Dev, |
| Func: addr.Func, |
| MissingParent: parent, |
| Comment: comment, |
| } |
| if addr.ConfigDump[0xa] == 0x04 && addr.ConfigDump[0xb] == 0x06 { |
| cur.PCIController = true |
| cur.ChildPCIBus = int(addr.ConfigDump[0x19]) |
| |
| loopCtr := 0 |
| for capPtr := addr.ConfigDump[0x34]; capPtr != 0; capPtr = addr.ConfigDump[capPtr+1] { |
| /* Avoid hangs. There are only 0x100 different possible values for capPtr. |
| If we iterate longer than that, we're in endless loop. */ |
| loopCtr++ |
| if loopCtr > 0x100 { |
| break |
| } |
| if addr.ConfigDump[capPtr] == 0x0d { |
| cur.SubVendor = GetLE16(addr.ConfigDump[capPtr+4 : capPtr+6]) |
| cur.SubSystem = GetLE16(addr.ConfigDump[capPtr+6 : capPtr+8]) |
| } |
| } |
| } else { |
| cur.SubVendor = GetLE16(addr.ConfigDump[0x2c:0x2e]) |
| cur.SubSystem = GetLE16(addr.ConfigDump[0x2e:0x30]) |
| } |
| unmatchedPCIDevices[addr.PCIAddr] = cur |
| } |
| |
| func PutPCIDev(addr PCIDevData, comment string) { |
| PutPCIDevParent(addr, comment, "") |
| } |
| |
| type GenericPCI struct { |
| Comment string |
| Bus0Subdiv string |
| MissingParent string |
| } |
| |
| type GenericVGA struct { |
| GenericPCI |
| } |
| |
| type DSDTInclude struct { |
| Comment string |
| File string |
| } |
| |
| type DSDTDefine struct { |
| Key string |
| Comment string |
| Value string |
| } |
| |
| var DSDTIncludes []DSDTInclude |
| var DSDTPCI0Includes []DSDTInclude |
| var DSDTDefines []DSDTDefine |
| |
| func (g GenericPCI) Scan(ctx Context, addr PCIDevData) { |
| PutPCIDevParent(addr, g.Comment, g.MissingParent) |
| } |
| |
| func (g GenericVGA) Scan(ctx Context, addr PCIDevData) { |
| KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x", |
| addr.PCIVenID, |
| addr.PCIDevID) |
| KconfigString["VGA_BIOS_FILE"] = fmt.Sprintf("pci%04x,%04x.rom", |
| addr.PCIVenID, |
| addr.PCIDevID) |
| PutPCIDevParent(addr, g.Comment, g.MissingParent) |
| } |
| |
| func makeKconfigName(ctx Context) { |
| kn := Create(ctx, "Kconfig.name") |
| defer kn.Close() |
| |
| fmt.Fprintf(kn, "config %s\n\tbool \"%s\"\n", ctx.KconfigName, ctx.Model) |
| } |
| |
| func makeComment(name string) string { |
| cmt, ok := KconfigComment[name] |
| if !ok { |
| return "" |
| } |
| return " # " + cmt |
| } |
| |
| func makeKconfig(ctx Context) { |
| kc := Create(ctx, "Kconfig") |
| defer kc.Close() |
| |
| fmt.Fprintf(kc, "if %s\n\n", ctx.KconfigName) |
| |
| fmt.Fprintf(kc, "config BOARD_SPECIFIC_OPTIONS # dummy\n\tdef_bool y\n") |
| keys := []string{} |
| for name, val := range KconfigBool { |
| if val { |
| keys = append(keys, name) |
| } |
| } |
| |
| sort.Strings(keys) |
| |
| for _, name := range keys { |
| fmt.Fprintf(kc, "\tselect %s%s\n", name, makeComment(name)) |
| } |
| |
| keys = nil |
| for name, val := range KconfigBool { |
| if !val { |
| keys = append(keys, name) |
| } |
| } |
| |
| sort.Strings(keys) |
| |
| for _, name := range keys { |
| fmt.Fprintf(kc, ` |
| config %s%s |
| bool |
| default n |
| `, name, makeComment(name)) |
| } |
| |
| keys = nil |
| for name, _ := range KconfigStringUnquoted { |
| keys = append(keys, name) |
| } |
| |
| sort.Strings(keys) |
| |
| for _, name := range keys { |
| fmt.Fprintf(kc, ` |
| config %s%s |
| string |
| default %s |
| `, name, makeComment(name), KconfigStringUnquoted[name]) |
| } |
| |
| keys = nil |
| for name, _ := range KconfigString { |
| keys = append(keys, name) |
| } |
| |
| sort.Strings(keys) |
| |
| for _, name := range keys { |
| fmt.Fprintf(kc, ` |
| config %s%s |
| string |
| default "%s" |
| `, name, makeComment(name), KconfigString[name]) |
| } |
| |
| keys = nil |
| for name, _ := range KconfigHex { |
| keys = append(keys, name) |
| } |
| |
| sort.Strings(keys) |
| |
| for _, name := range keys { |
| fmt.Fprintf(kc, ` |
| config %s%s |
| hex |
| default 0x%x |
| `, name, makeComment(name), KconfigHex[name]) |
| } |
| |
| keys = nil |
| for name, _ := range KconfigInt { |
| keys = append(keys, name) |
| } |
| |
| sort.Strings(keys) |
| |
| for _, name := range keys { |
| fmt.Fprintf(kc, ` |
| config %s%s |
| int |
| default %d |
| `, name, makeComment(name), KconfigInt[name]) |
| } |
| |
| fmt.Fprintf(kc, "endif\n") |
| } |
| |
| const MoboDir = "/src/mainboard/" |
| |
| func makeVendor(ctx Context) { |
| vendor := ctx.Vendor |
| vendorSane := ctx.SaneVendor |
| vendorDir := *FlagOutDir + MoboDir + vendorSane |
| vendorUpper := strings.ToUpper(vendorSane) |
| kconfig := vendorDir + "/Kconfig" |
| if _, err := os.Stat(kconfig); os.IsNotExist(err) { |
| f, err := os.Create(kconfig) |
| if err != nil { |
| log.Fatal(err) |
| } |
| defer f.Close() |
| f.WriteString(`if VENDOR_` + vendorUpper + ` |
| |
| choice |
| prompt "Mainboard model" |
| |
| source "src/mainboard/` + vendorSane + `/*/Kconfig.name" |
| |
| endchoice |
| |
| source "src/mainboard/` + vendorSane + `/*/Kconfig" |
| |
| config MAINBOARD_VENDOR |
| string |
| default "` + vendor + `" |
| |
| endif # VENDOR_` + vendorUpper + "\n") |
| } |
| kconfigName := vendorDir + "/Kconfig.name" |
| if _, err := os.Stat(kconfigName); os.IsNotExist(err) { |
| f, err := os.Create(kconfigName) |
| if err != nil { |
| log.Fatal(err) |
| } |
| defer f.Close() |
| f.WriteString(`config VENDOR_` + vendorUpper + ` |
| bool "` + vendor + `" |
| `) |
| } |
| |
| } |
| |
| func GuessECGPE(ctx Context) int { |
| /* FIXME:XX Use iasl -d and/or better parsing */ |
| dsdt := ctx.InfoSource.GetACPI()["DSDT"] |
| idx := bytes.Index(dsdt, []byte{0x08, '_', 'G', 'P', 'E', 0x0a}) /* Name (_GPE, byte). */ |
| if idx > 0 { |
| return int(dsdt[idx+6]) |
| } |
| return -1 |
| } |
| |
| func GuessSPDMap(ctx Context) []uint8 { |
| dmi := ctx.InfoSource.GetDMI() |
| |
| if dmi.Vendor == "LENOVO" { |
| return []uint8{0x50, 0x52, 0x51, 0x53} |
| } |
| return []uint8{0x50, 0x51, 0x52, 0x53} |
| } |
| |
| func main() { |
| flag.Parse() |
| |
| ctx := Context{} |
| |
| ctx.InfoSource = MakeLogReader() |
| |
| dmi := ctx.InfoSource.GetDMI() |
| |
| ctx.Vendor = dmi.Vendor |
| |
| if dmi.Vendor == "LENOVO" { |
| ctx.Model = dmi.Version |
| } else { |
| ctx.Model = dmi.Model |
| } |
| |
| if dmi.IsLaptop { |
| KconfigBool["SYSTEM_TYPE_LAPTOP"] = true |
| } |
| ctx.SaneVendor = sanitize(ctx.Vendor) |
| for { |
| last := ctx.SaneVendor |
| for _, suf := range []string{"_inc", "_co", "_corp"} { |
| ctx.SaneVendor = strings.TrimSuffix(ctx.SaneVendor, suf) |
| } |
| if last == ctx.SaneVendor { |
| break |
| } |
| } |
| ctx.MoboID = ctx.SaneVendor + "/" + sanitize(ctx.Model) |
| ctx.KconfigName = "BOARD_" + strings.ToUpper(ctx.SaneVendor+"_"+sanitize(ctx.Model)) |
| ctx.BaseDirectory = *FlagOutDir + MoboDir + ctx.MoboID |
| KconfigStringUnquoted["MAINBOARD_DIR"] = ctx.MoboID |
| KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model |
| |
| os.MkdirAll(ctx.BaseDirectory, 0700) |
| |
| makeVendor(ctx) |
| |
| ScanRoot(ctx) |
| |
| if len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 { |
| mf := Create(ctx, "Makefile.inc") |
| defer mf.Close() |
| writeMF(mf, ROMStageFiles, "romstage") |
| writeMF(mf, RAMStageFiles, "ramstage") |
| writeMF(mf, SMMFiles, "smm") |
| } |
| |
| devtree := Create(ctx, "devicetree.cb") |
| defer devtree.Close() |
| |
| MatchDev(&DevTree) |
| WriteDev(devtree, 0, DevTree) |
| |
| if MainboardInit != "" || MainboardEnable != "" || MainboardIncludes != nil { |
| mainboard := Create(ctx, "mainboard.c") |
| defer mainboard.Close() |
| mainboard.WriteString("#include <device/device.h>\n") |
| for _, include := range MainboardIncludes { |
| mainboard.WriteString("#include <" + include + ">\n") |
| } |
| mainboard.WriteString("\n") |
| if MainboardInit != "" { |
| mainboard.WriteString(`static void mainboard_init(device_t dev) |
| { |
| ` + MainboardInit + "}\n\n") |
| } |
| if MainboardInit != "" || MainboardEnable != "" { |
| mainboard.WriteString("static void mainboard_enable(device_t dev)\n{\n") |
| if MainboardInit != "" { |
| mainboard.WriteString("\tdev->ops->init = mainboard_init;\n\n") |
| } |
| mainboard.WriteString(MainboardEnable) |
| mainboard.WriteString("}\n\n") |
| mainboard.WriteString(`struct chip_operations mainboard_ops = { |
| .enable_dev = mainboard_enable, |
| }; |
| `) |
| } |
| } |
| |
| at := Create(ctx, "acpi_tables.c") |
| defer at.Close() |
| at.WriteString("/* dummy */\n") |
| |
| bi := Create(ctx, "board_info.txt") |
| defer bi.Close() |
| |
| fixme := "" |
| |
| if dmi.IsLaptop { |
| bi.WriteString("Category: laptop\n") |
| } else { |
| bi.WriteString("Category: desktop\n") |
| fixme += "check category, " |
| } |
| |
| missing := "ROM package, ROM socketed" |
| |
| if ROMProtocol != "" { |
| fmt.Fprintf(bi, "ROM protocol: %s\n", ROMProtocol) |
| } else { |
| missing += ", ROM protocol" |
| } |
| |
| if FlashROMSupport != "" { |
| fmt.Fprintf(bi, "Flashrom support: %s\n", FlashROMSupport) |
| } else { |
| missing += ", Flashrom support" |
| } |
| |
| missing += ", Release year" |
| |
| if fixme != "" { |
| fmt.Fprintf(bi, "FIXME: %s, put %s\n", fixme, missing) |
| } else { |
| fmt.Fprintf(bi, "FIXME: put %s\n", missing) |
| } |
| |
| rs := Create(ctx, "romstage.c") |
| defer rs.Close() |
| rs.WriteString("/* dummy file */\n") |
| |
| if ROMSizeKB == 0 { |
| KconfigBool["BOARD_ROMSIZE_KB_2048"] = true |
| KconfigComment["BOARD_ROMSIZE_KB_2048"] = "FIXME: correct this" |
| } else { |
| KconfigBool[fmt.Sprintf("BOARD_ROMSIZE_KB_%d", ROMSizeKB)] = true |
| } |
| |
| makeKconfig(ctx) |
| makeKconfigName(ctx) |
| |
| dsdt := Create(ctx, "dsdt.asl") |
| defer dsdt.Close() |
| |
| for _, define := range DSDTDefines { |
| if define.Comment != "" { |
| fmt.Fprintf(dsdt, "\t/* %s. */\n", define.Comment) |
| } |
| dsdt.WriteString("#define " + define.Key + " " + define.Value + "\n") |
| } |
| |
| dsdt.WriteString( |
| `DefinitionBlock( |
| "dsdt.aml", |
| "DSDT", |
| 0x03, // DSDT revision: ACPI v3.0 |
| "COREv4", // OEM id |
| "COREBOOT", // OEM table id |
| 0x20141018 // OEM revision |
| ) |
| { |
| // Some generic macros |
| #include "acpi/platform.asl" |
| `) |
| |
| for _, x := range DSDTIncludes { |
| if x.Comment != "" { |
| fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment) |
| } |
| fmt.Fprintf(dsdt, "\t#include <%s>\n", x.File) |
| } |
| |
| dsdt.WriteString(` |
| Scope (\_SB) { |
| Device (PCI0) |
| { |
| `) |
| for _, x := range DSDTPCI0Includes { |
| if x.Comment != "" { |
| fmt.Fprintf(dsdt, "\t/* %s. */\n", x.Comment) |
| } |
| fmt.Fprintf(dsdt, "\t\t#include <%s>\n", x.File) |
| } |
| dsdt.WriteString( |
| ` } |
| } |
| } |
| `) |
| |
| } |