Yes, the DSDT revision is the OEM revision. But most certainly not that of the board being ported. Because no one seems to care about the value (newer boards inexplicably use lower values even though this represents a date in 0xYYYYMMDD format), simply drop the incorrect comment. Should save a bit of effort when reviewing mainboard ports: no longer will one have to ask authors to drop the comment. Change-Id: I9c425573e4fcb0f670a780e7821e815eadc8a2aa Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/82401 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
		
			
				
	
	
		
			908 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			908 lines
		
	
	
		
			20 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 BootBlockFiles map[string]string = map[string]string{}
 | |
| 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 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)
 | |
| 	result = strings.Replace(result, "-", "_", -1)
 | |
| 	for strings.HasSuffix(result, ".") {
 | |
| 		result = result[0 : len(result)-1]
 | |
| 	}
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| func AddBootBlockFile(Name string, Condition string) {
 | |
| 	BootBlockFiles[Name] = Condition
 | |
| }
 | |
| 
 | |
| 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(f *os.File) {
 | |
| 	fmt.Fprintln(f, "/* SPDX-License-Identifier: GPL-2.0-only */")
 | |
| 	fmt.Fprintln(f)
 | |
| }
 | |
| 
 | |
| 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
 | |
| 	alias             string
 | |
| 	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, alias string, 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":
 | |
| 		if alias != "" {
 | |
| 			fmt.Fprintf(dt, "device ref %s ", alias)
 | |
| 		} else {
 | |
| 			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 {
 | |
| 		alias = ""
 | |
| 		for _, slot := range dev.PCISlots {
 | |
| 			if slot.PCIAddr.Bus == child.Bus &&
 | |
| 				slot.PCIAddr.Dev == child.Dev && slot.PCIAddr.Func == child.Func {
 | |
| 				alias = slot.alias
 | |
| 			}
 | |
| 		}
 | |
| 		WriteDev(dt, offset+1, alias, 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)
 | |
| }
 | |
| 
 | |
| var IGDEnabled bool = false
 | |
| 
 | |
| func (g GenericVGA) Scan(ctx Context, addr PCIDevData) {
 | |
| 	KconfigString["VGA_BIOS_ID"] = fmt.Sprintf("%04x,%04x",
 | |
| 		addr.PCIVenID,
 | |
| 		addr.PCIDevID)
 | |
| 	PutPCIDevParent(addr, g.Comment, g.MissingParent)
 | |
| 	IGDEnabled = true
 | |
| }
 | |
| 
 | |
| 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\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 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
 | |
| 	KconfigString["MAINBOARD_DIR"] = ctx.MoboID
 | |
| 	KconfigString["MAINBOARD_PART_NUMBER"] = ctx.Model
 | |
| 
 | |
| 	os.MkdirAll(ctx.BaseDirectory, 0700)
 | |
| 
 | |
| 	makeVendor(ctx)
 | |
| 
 | |
| 	ScanRoot(ctx)
 | |
| 
 | |
| 	if IGDEnabled {
 | |
| 		KconfigBool["MAINBOARD_HAS_LIBGFXINIT"] = true
 | |
| 		KconfigComment["MAINBOARD_HAS_LIBGFXINIT"] = "FIXME: check this"
 | |
| 		AddRAMStageFile("gma-mainboard.ads", "CONFIG_MAINBOARD_USE_LIBGFXINIT")
 | |
| 	}
 | |
| 
 | |
| 	if len(BootBlockFiles) > 0 || len(ROMStageFiles) > 0 || len(RAMStageFiles) > 0 || len(SMMFiles) > 0 {
 | |
| 		mf := Create(ctx, "Makefile.mk")
 | |
| 		defer mf.Close()
 | |
| 		writeMF(mf, BootBlockFiles, "bootblock")
 | |
| 		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()
 | |
| 		Add_gpl(mainboard)
 | |
| 		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(struct device *dev)
 | |
| {
 | |
| ` + MainboardInit + "}\n\n")
 | |
| 		}
 | |
| 		if MainboardInit != "" || MainboardEnable != "" {
 | |
| 			mainboard.WriteString("static void mainboard_enable(struct device *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,
 | |
| };
 | |
| `)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	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)
 | |
| 	}
 | |
| 
 | |
| 	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")
 | |
| 	}
 | |
| 
 | |
| 	Add_gpl(dsdt)
 | |
| 	dsdt.WriteString(
 | |
| 		`
 | |
| #include <acpi/acpi.h>
 | |
| 
 | |
| DefinitionBlock(
 | |
| 	"dsdt.aml",
 | |
| 	"DSDT",
 | |
| 	ACPI_DSDT_REV_2,
 | |
| 	OEM_ID,
 | |
| 	ACPI_TABLE_CREATOR,
 | |
| 	0x20141018
 | |
| )
 | |
| {
 | |
| 	#include <acpi/dsdt_top.asl>
 | |
| 	#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(`
 | |
| 	Device (\_SB.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(
 | |
| 		`	}
 | |
| }
 | |
| `)
 | |
| 
 | |
| 	if IGDEnabled {
 | |
| 		gma := Create(ctx, "gma-mainboard.ads")
 | |
| 		defer gma.Close()
 | |
| 
 | |
| 		gma.WriteString(`-- SPDX-License-Identifier: GPL-2.0-or-later
 | |
| 
 | |
| with HW.GFX.GMA;
 | |
| with HW.GFX.GMA.Display_Probing;
 | |
| 
 | |
| use HW.GFX.GMA;
 | |
| use HW.GFX.GMA.Display_Probing;
 | |
| 
 | |
| private package GMA.Mainboard is
 | |
| 
 | |
|    -- FIXME: check this
 | |
|    ports : constant Port_List :=
 | |
|      (DP1,
 | |
|       DP2,
 | |
|       DP3,
 | |
|       HDMI1,
 | |
|       HDMI2,
 | |
|       HDMI3,
 | |
|       Analog,
 | |
|       LVDS,
 | |
|       eDP);
 | |
| 
 | |
| end GMA.Mainboard;
 | |
| `)
 | |
| 	}
 | |
| }
 |