autoport: Write autoport together with porting guide for sandy/ivybridge.
This should be able to generate bootable ports for sandy/ivy, possible with minor fixes. Howto is in readme.md Change-Id: Ia126cf0939ef2dc2cdbb7ea100d2b63ea6b02f28 Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com> Reviewed-on: http://review.coreboot.org/7131 Tested-by: build bot (Jenkins) Reviewed-by: Edward O'Callaghan <edward.ocallaghan@koparo.com>
This commit is contained in:
858
util/autoport/main.go
Normal file
858
util/autoport/main.go
Normal file
@@ -0,0 +1,858 @@
|
||||
/* 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
|
||||
}
|
||||
|
||||
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 := sanitize(ctx.Vendor)
|
||||
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, 0x51, 0x52, 0x53}
|
||||
}
|
||||
return []uint8{0x50, 0x52, 0x51, 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.MoboID = sanitize(ctx.Vendor) + "/" + sanitize(ctx.Model)
|
||||
ctx.KconfigName = "BOARD_" + strings.ToUpper(sanitize(ctx.Vendor)+"_"+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(
|
||||
` }
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
}
|
Reference in New Issue
Block a user