5930285206
The idea behind this not to enforce a license on autogenerated code but is simply out of convenience in the case one wants to make the result public (in which case it needs to have these license headers). Change-Id: I1d6b48762b1249bb0becb178a30e1396bf6978fc Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/19510 Reviewed-by: Patrick Rudolph <siro@das-labor.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de>
891 lines
19 KiB
Go
891 lines
19 KiB
Go
/* 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
|
|
HasPS2() bool
|
|
}
|
|
|
|
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 Add_gpl(fp *os.File) {
|
|
fp.WriteString(`/*
|
|
* This file is part of the coreboot project.
|
|
*
|
|
* Copyright (C) 2008-2009 coresystems GmbH
|
|
* Copyright (C) 2014 Vladimir Serbinenko
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; version 2 of
|
|
* the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
`)
|
|
}
|
|
|
|
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(
|
|
` }
|
|
}
|
|
}
|
|
`)
|
|
|
|
}
|