summaryrefslogtreecommitdiff
path: root/util/autoport/log_reader.go
diff options
context:
space:
mode:
authorNicholas Chin <nic.c3.14@gmail.com>2024-03-18 10:45:05 -0600
committerNicholas Chin <nic.c3.14@gmail.com>2024-03-18 10:45:05 -0600
commit8cba237086dfbb312a5913bb75eef4f6046aeae5 (patch)
treea208e8ff3e8b628b1615918cbb55b6ce351cfe54 /util/autoport/log_reader.go
parentc578fe56c36f94af5c51a1be27a1a1c4b57a4289 (diff)
util: Import autoport with Haswell patches
This is a copy of coreboot's autoport utility, with a patch applied to support Haswell/Lynx Point platforms. That patch is currently in review on coreboot's Gerrit. https://review.coreboot.org/c/coreboot/+/30890 Signed-off-by: Nicholas Chin <nic.c3.14@gmail.com>
Diffstat (limited to 'util/autoport/log_reader.go')
-rw-r--r--util/autoport/log_reader.go417
1 files changed, 417 insertions, 0 deletions
diff --git a/util/autoport/log_reader.go b/util/autoport/log_reader.go
new file mode 100644
index 00000000..b0518d25
--- /dev/null
+++ b/util/autoport/log_reader.go
@@ -0,0 +1,417 @@
+package main
+
+import (
+ "bufio"
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+type LogDevReader struct {
+ InputDirectory string
+ ACPITables map[string][]byte
+ EC []byte
+}
+
+func isXDigit(x uint8) bool {
+ if x >= '0' && x <= '9' {
+ return true
+ }
+ if x >= 'a' && x <= 'f' {
+ return true
+ }
+ if x >= 'A' && x <= 'F' {
+ return true
+ }
+ return false
+}
+
+type HexLine struct {
+ length uint
+ values [16]byte
+ start uint
+}
+
+func (l *LogDevReader) ReadHexLine(line string) (hex HexLine) {
+ hex.start = 0
+ line = strings.Trim(line, " ")
+ fmt.Sscanf(line, "%x:", &hex.start)
+ ll, _ := fmt.Sscanf(line, "%x: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", &hex.start,
+ &hex.values[0], &hex.values[1], &hex.values[2],
+ &hex.values[3], &hex.values[4], &hex.values[5],
+ &hex.values[6], &hex.values[7], &hex.values[8],
+ &hex.values[9], &hex.values[10], &hex.values[11],
+ &hex.values[12], &hex.values[13], &hex.values[14],
+ &hex.values[15])
+ hex.length = uint(ll - 1)
+ return
+}
+
+func (l *LogDevReader) AssignHexLine(inp string, target []byte) []byte {
+ hex := l.ReadHexLine(inp)
+ if hex.start+hex.length > uint(len(target)) {
+ target = target[0 : hex.start+hex.length]
+ }
+ copy(target[hex.start:hex.start+hex.length], hex.values[0:hex.length])
+ return target
+}
+
+func (l *LogDevReader) GetEC() []byte {
+ if l.EC != nil {
+ return l.EC
+ }
+ l.EC = make([]byte, 0x100, 0x100)
+
+ file, err := os.Open(l.InputDirectory + "/ectool.log")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+
+ for scanner.Scan() {
+ line := scanner.Text()
+ if len(line) > 7 && isXDigit(line[0]) && isXDigit(line[1]) && line[2] == ':' {
+ l.EC = l.AssignHexLine(line, l.EC)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+
+ return l.EC
+}
+
+func (l *LogDevReader) GetACPI() (Tables map[string][]byte) {
+ if l.ACPITables != nil {
+ return l.ACPITables
+ }
+ l.ACPITables = Tables
+
+ file, err := os.Open(l.InputDirectory + "/acpidump.log")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+
+ Tables = map[string][]byte{}
+
+ curTable := ""
+ for scanner.Scan() {
+ line := scanner.Text()
+ /* Only supports ACPI tables up to 0x100000 in size, FIXME if needed */
+ is_hexline, _ := regexp.MatchString(" *[0-9A-Fa-f]{4,5}: ", line)
+ switch {
+ case len(line) >= 6 && line[5] == '@':
+ curTable = line[0:4]
+ Tables[curTable] = make([]byte, 0, 0x100000)
+ case is_hexline:
+ Tables[curTable] = l.AssignHexLine(line, Tables[curTable])
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+
+ return
+}
+
+func (l *LogDevReader) GetPCIList() (PCIList []PCIDevData) {
+ file, err := os.Open(l.InputDirectory + "/lspci.log")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+
+ PCIList = []PCIDevData{}
+
+ for scanner.Scan() {
+ line := scanner.Text()
+ switch {
+ case !(len(line) < 7 || !isXDigit(line[0]) || !isXDigit(line[1]) || line[2] != ':' || !isXDigit(line[3]) || !isXDigit(line[4]) || line[5] != '.' || !isXDigit(line[6])):
+ cur := PCIDevData{}
+ fmt.Sscanf(line, "%x:%x.%x", &cur.Bus, &cur.Dev, &cur.Func)
+ lc := strings.LastIndex(line, ":")
+ li := strings.LastIndex(line[0:lc], "[")
+ if li < 0 {
+ continue
+ }
+ ven := 0
+ dev := 0
+ fmt.Sscanf(line[li+1:], "%x:%x", &ven, &dev)
+ cur.PCIDevID = uint16(dev)
+ cur.PCIVenID = uint16(ven)
+ cur.ConfigDump = make([]byte, 0x100, 0x1000)
+ PCIList = append(PCIList, cur)
+ case len(line) > 7 && isXDigit(line[0]) && line[1] == '0' && line[2] == ':':
+ start := 0
+ fmt.Sscanf(line, "%x:", &start)
+ cur := &PCIList[len(PCIList)-1]
+ cur.ConfigDump = l.AssignHexLine(line, cur.ConfigDump)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+
+ return
+}
+
+func (l *LogDevReader) GetInteltool() (ret InteltoolData) {
+ file, err := os.Open(l.InputDirectory + "/inteltool.log")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ paragraph := ""
+ ret.GPIO = map[uint16]uint32{}
+ ret.RCBA = map[uint16]uint32{}
+ ret.IOBP = map[uint32]uint32{}
+ ret.IGD = map[uint32]uint32{}
+ ret.MCHBAR = map[uint16]uint32{}
+ ret.PMBASE = map[uint16]uint32{}
+ for scanner.Scan() {
+ line := scanner.Text()
+ switch {
+ case len(line) > 7 && line[0] == '0' && line[1] == 'x' && line[6] == ':' && paragraph == "RCBA":
+ addr, value := 0, 0
+ fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
+ ret.RCBA[uint16(addr)] = uint32(value)
+ case len(line) > 11 && line[0] == '0' && line[1] == 'x' && line[10] == ':' && paragraph == "IOBP":
+ addr, value := 0, 0
+ fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
+ ret.IOBP[uint32(addr)] = uint32(value)
+ case len(line) > 9 && line[0] == '0' && line[1] == 'x' && line[8] == ':' && paragraph == "IGD":
+ addr, value := 0, 0
+ fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
+ ret.IGD[uint32(addr)] = uint32(value)
+ case len(line) > 7 && line[0] == '0' && line[1] == 'x' && line[6] == ':' && paragraph == "MCHBAR":
+ addr, value := 0, 0
+ fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
+ ret.MCHBAR[uint16(addr)] = uint32(value)
+ case strings.Contains(line, "DEFAULT"):
+ continue
+ case strings.Contains(line, "DIFF"):
+ continue
+ case strings.HasPrefix(line, "gpiobase"):
+ addr, value := 0, 0
+ fmt.Sscanf(line, "gpiobase+0x%x: 0x%x", &addr, &value)
+ ret.GPIO[uint16(addr)] = uint32(value)
+ case strings.HasPrefix(line, "pmbase"):
+ addr, value := 0, 0
+ fmt.Sscanf(line, "pmbase+0x%x: 0x%x", &addr, &value)
+ ret.PMBASE[uint16(addr)] = uint32(value)
+ case strings.HasPrefix(line, "============="):
+ paragraph = strings.Trim(line, "= ")
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+ return
+}
+
+func (l *LogDevReader) GetDMI() (ret DMIData) {
+ file, err := os.Open(l.InputDirectory + "/dmidecode.log")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ paragraph := ""
+ for scanner.Scan() {
+ line := scanner.Text()
+ if !strings.HasPrefix(line, "\t") {
+ paragraph = strings.TrimSpace(line)
+ continue
+ }
+ idx := strings.Index(line, ":")
+ if idx < 0 {
+ continue
+ }
+ name := strings.TrimSpace(line[0:idx])
+ value := strings.TrimSpace(line[idx+1:])
+ switch paragraph + ":" + name {
+ case "System Information:Manufacturer":
+ ret.Vendor = value
+ case "System Information:Product Name":
+ ret.Model = value
+ case "System Information:Version":
+ ret.Version = value
+ case "Chassis Information:Type":
+ ret.IsLaptop = (value == "Notebook" || value == "Laptop")
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+ return
+}
+
+func (l *LogDevReader) GetAzaliaCodecs() (ret []AzaliaCodec) {
+ cardno := -1
+ for i := 0; i < 10; i++ {
+ pin, err := os.Open(l.InputDirectory + "/pin_hwC" + strconv.Itoa(i) + "D0")
+ if err == nil {
+ pin.Close()
+ cardno = i
+ break
+ }
+ }
+ if cardno == -1 {
+ return
+ }
+ for codecno := 0; codecno < 10; codecno++ {
+ cur := AzaliaCodec{CodecNo: codecno, PinConfig: map[int]uint32{}}
+ codec, err := os.Open(l.InputDirectory + "/codec#" + strconv.Itoa(codecno))
+ if err != nil {
+ continue
+ }
+ defer codec.Close()
+ pin, err := os.Open(l.InputDirectory + "/pin_hwC" + strconv.Itoa(cardno) +
+ "D" + strconv.Itoa(codecno))
+ if err != nil {
+ continue
+ }
+ defer pin.Close()
+
+ scanner := bufio.NewScanner(codec)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.HasPrefix(line, "Codec:") {
+ fmt.Sscanf(line, "Codec: %s", &cur.Name)
+ continue
+ }
+ if strings.HasPrefix(line, "Vendor Id:") {
+ fmt.Sscanf(line, "Vendor Id: 0x%x", &cur.VendorID)
+ continue
+ }
+ if strings.HasPrefix(line, "Subsystem Id:") {
+ fmt.Sscanf(line, "Subsystem Id: 0x%x", &cur.SubsystemID)
+ continue
+ }
+ }
+
+ scanner = bufio.NewScanner(pin)
+ for scanner.Scan() {
+ line := scanner.Text()
+ addr := 0
+ val := uint32(0)
+ fmt.Sscanf(line, "0x%x 0x%x", &addr, &val)
+ cur.PinConfig[addr] = val
+ }
+ ret = append(ret, cur)
+ }
+ return
+}
+
+func (l *LogDevReader) GetIOPorts() []IOPorts {
+ file, err := os.Open(l.InputDirectory + "/ioports.log")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+ scanner := bufio.NewScanner(file)
+ ret := make([]IOPorts, 0, 100)
+ for scanner.Scan() {
+ line := scanner.Text()
+ el := IOPorts{}
+ fmt.Sscanf(line, " %x-%x : %s", &el.Start, &el.End, &el.Usage)
+ ret = append(ret, el)
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+ return ret
+
+}
+
+func (l *LogDevReader) GetCPUModel() (ret []uint32) {
+ file, err := os.Open(l.InputDirectory + "/cpuinfo.log")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ ret = make([]uint32, 0, 100)
+ proc := 0
+ for scanner.Scan() {
+ line := scanner.Text()
+ sep := strings.Index(line, ":")
+ if sep < 0 {
+ continue
+ }
+ key := strings.TrimSpace(line[0:sep])
+ val := strings.TrimSpace(line[sep+1:])
+
+ if key == "processor" {
+ proc, _ := strconv.Atoi(val)
+ if len(ret) <= proc {
+ ret = ret[0 : proc+1]
+ }
+ continue
+ }
+ if key == "cpu family" {
+ family, _ := strconv.Atoi(val)
+ ret[proc] |= uint32(((family & 0xf) << 8) | ((family & 0xff0) << 16))
+ }
+ if key == "model" {
+ model, _ := strconv.Atoi(val)
+ ret[proc] |= uint32(((model & 0xf) << 4) | ((model & 0xf0) << 12))
+ }
+ if key == "stepping" {
+ stepping, _ := strconv.Atoi(val)
+ ret[proc] |= uint32(stepping & 0xf)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+ return
+}
+
+func (l *LogDevReader) HasPS2() bool {
+ file, err := os.Open(l.InputDirectory + "/input_bustypes.log")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.Index(line, "0011") >= 0 {
+ return true
+ }
+ }
+ return false
+}
+
+var FlagLogInput = flag.String("input_log", ".", "Input log directory")
+var FlagLogMkLogs = flag.Bool("make_logs", false, "Dump logs")
+
+func MakeLogReader() *LogDevReader {
+ if *FlagLogMkLogs {
+ MakeLogs(*FlagLogInput)
+ }
+ return &LogDevReader{InputDirectory: *FlagLogInput}
+}