xref: /aosp_15_r20/external/coreboot/util/autoport/log_maker.go (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1package main
2
3import (
4	"errors"
5	"fmt"
6	"io"
7	"io/ioutil"
8	"log"
9	"os"
10	"os/exec"
11	"strings"
12	"bytes"
13)
14
15func TryRunAndSave(output string, name string, arg []string) error {
16	cmd := exec.Command(name, arg...)
17
18	f, err := os.Create(output)
19	if err != nil {
20		log.Fatal(err)
21	}
22
23	cmd.Stdout = f
24	cmd.Stderr = f
25
26	err = cmd.Start()
27	if err != nil {
28		return err
29	}
30	cmd.Wait()
31	return nil
32}
33
34func RunAndSave(output string, name string, arg ...string) {
35	err := TryRunAndSave(output, name, arg)
36	if err == nil {
37		return
38	}
39	idx := strings.LastIndex(name, "/")
40	relname := name
41	if idx >= 0 {
42		relname = name[idx+1:]
43	}
44	relname = "./" + relname
45	err = TryRunAndSave(output, relname, arg)
46	if err != nil {
47		log.Fatal(err)
48	}
49}
50
51const MAXPROMPTRETRY = 3
52
53func PromptUser(prompt string, opts []string) (match string, err error) {
54	for i := 1; i < MAXPROMPTRETRY; i++ {
55		fmt.Printf("%s. (%s) Default:%s\n", prompt,
56		           strings.Join(opts, "/"), opts[0])
57		var usrInput string
58		fmt.Scanln(&usrInput)
59
60		// Check for default entry
61		if usrInput == "" {
62			match = opts[0]
63			return
64		}
65
66		for _, opt := range opts {
67			if opt == usrInput {
68				match = opt
69				return
70			}
71		}
72	}
73	err = errors.New("max retries exceeded")
74	fmt.Fprintln(os.Stderr, "ERROR: max retries exceeded")
75	return
76}
77
78func AppendYesNo(yesFirst bool, yeah []string, nope []string) []string {
79	if yesFirst {
80		return append(yeah, nope...)
81	} else {
82		return append(nope, yeah...)
83	}
84}
85
86func PromptUserBool(prompt string, fallback bool) bool {
87	yeah := []string{"y", "yes"}
88	nope := []string{"n", "no"}
89
90	opt, err := PromptUser(prompt, AppendYesNo(fallback, yeah, nope))
91	if err != nil {
92		// Continue even if there is an error
93		return fallback
94	}
95	for _, val := range yeah {
96		if opt == val {
97			return true
98		}
99	}
100	return false
101}
102
103func MakeHDALogs(outDir string, cardName string) {
104	SysDir := "/sys/class/sound/" + cardName + "/"
105	files, _ := ioutil.ReadDir(SysDir)
106	for _, f := range files {
107		if (strings.HasPrefix(f.Name(), "hw") || strings.HasPrefix(f.Name(), "hdaudio")) && f.IsDir() {
108			in, err := os.Open(SysDir + f.Name() + "/init_pin_configs")
109			defer in.Close()
110			if err != nil {
111				log.Fatal(err)
112			}
113			out, err := os.Create(outDir + "/pin_" + strings.Replace(f.Name(), "hdaudio", "hw", -1))
114			if err != nil {
115				log.Fatal(err)
116			}
117			defer out.Close()
118			io.Copy(out, in)
119		}
120	}
121
122	ProcDir := "/proc/asound/" + cardName + "/"
123	files, _ = ioutil.ReadDir(ProcDir)
124	for _, f := range files {
125		if strings.HasPrefix(f.Name(), "codec#") && !f.IsDir() {
126			in, err := os.Open(ProcDir + f.Name())
127			defer in.Close()
128			if err != nil {
129				log.Fatal(err)
130			}
131			out, err := os.Create(outDir + "/" + f.Name())
132			if err != nil {
133				log.Fatal(err)
134			}
135			defer out.Close()
136			io.Copy(out, in)
137		}
138	}
139}
140
141func MakeLogs(outDir string) {
142	os.MkdirAll(outDir, 0700)
143	RunAndSave(outDir+"/lspci.log", "lspci", "-nnvvvxxxx")
144	RunAndSave(outDir+"/dmidecode.log", "dmidecode")
145	RunAndSave(outDir+"/acpidump.log", "acpidump")
146
147	probeGFX := PromptUserBool("WARNING: The following tool MAY cause your system to hang when it attempts "+
148		"to probe for graphics registers.  Having the graphics registers will help create a better port. "+
149		"Should autoport probe these registers?",
150		true)
151
152	inteltoolArgs := "-a"
153	if probeGFX {
154		inteltoolArgs += "f"
155	}
156
157	RunAndSave(outDir+"/inteltool.log", "../inteltool/inteltool", inteltoolArgs)
158	RunAndSave(outDir+"/ectool.log", "../ectool/ectool", "-pd")
159	RunAndSave(outDir+"/superiotool.log", "../superiotool/superiotool", "-ade")
160
161	SysSound := "/sys/class/sound/"
162	card := ""
163	cards, _ := ioutil.ReadDir(SysSound)
164	for _, f := range cards {
165		if strings.HasPrefix(f.Name(), "card") {
166			cid, err := ioutil.ReadFile(SysSound + f.Name() + "/id")
167			if err == nil && bytes.Equal(cid, []byte("PCH\n")) {
168				fmt.Fprintln(os.Stderr, "PCH sound card is", f.Name())
169				card = f.Name()
170			}
171		}
172	}
173
174	if card != "" {
175		MakeHDALogs(outDir, card)
176	} else {
177		fmt.Fprintln(os.Stderr, "HDAudio not found on PCH.")
178	}
179
180	for _, fname := range []string{"cpuinfo", "ioports"} {
181		in, err := os.Open("/proc/" + fname)
182		defer in.Close()
183		if err != nil {
184			log.Fatal(err)
185		}
186		out, err := os.Create(outDir + "/" + fname + ".log")
187		if err != nil {
188			log.Fatal(err)
189		}
190		defer out.Close()
191		io.Copy(out, in)
192	}
193
194	out, err := os.Create(outDir + "/input_bustypes.log")
195	if err != nil {
196		log.Fatal(err)
197	}
198	defer out.Close()
199
200	ClassInputDir := "/sys/class/input/"
201	files, _ := ioutil.ReadDir(ClassInputDir)
202	for _, f := range files {
203		if strings.HasPrefix(f.Name(), "input") && !f.Mode().IsRegular() { /* Allow both dirs and symlinks.  */
204			in, err := os.Open(ClassInputDir + f.Name() + "/id/bustype")
205			defer in.Close()
206			if err != nil {
207				log.Fatal(err)
208			}
209			io.Copy(out, in)
210		}
211	}
212}
213