This won't compile since '-' is an operator in C. Change-Id: Icf900c959cbcbd0b07cd83a1f6866bf255fdcf01 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/23321 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Christoph Pomaska <cp_public@posteo.de> Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
		
			
				
	
	
		
			893 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			893 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 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)
 | |
| 	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(
 | |
| 		`		}
 | |
| 	}
 | |
| }
 | |
| `)
 | |
| 
 | |
| }
 |