util/ifdtool: Fix memory leaks
[coreboot2.git] / util / autoport / log_maker.go
blob6183fb4d8078ba0b0ca9e42dff81451461979aee
1 package main
3 import (
4 "errors"
5 "fmt"
6 "io"
7 "io/ioutil"
8 "log"
9 "os"
10 "os/exec"
11 "strings"
12 "bytes"
15 type LogMakingProgram struct {
16 name string
17 prefixes []string
18 args []string
21 func ExecCommand(sudo bool, name string, arg []string) *exec.Cmd {
22 if sudo {
23 return exec.Command("sudo", append([]string{name}, arg...)...)
24 } else {
25 return exec.Command(name, arg...)
29 func (prog LogMakingProgram) TryRunAndSave(output string, sudo bool, prefix string) error {
30 f, err := os.Create(output)
31 if err != nil {
32 log.Fatal(err)
34 defer f.Close()
36 cmd := ExecCommand(sudo, prefix+prog.name, prog.args)
37 cmd.Stdout = f
38 cmd.Stderr = f
40 err = cmd.Start()
41 if err != nil {
42 return err
44 return cmd.Wait()
47 func (prog LogMakingProgram) RunAndSave(outDir string, sudo bool) {
48 output := fmt.Sprintf("%s/%s.log", outDir, prog.name)
49 cmdline := strings.Join(append([]string{prog.name}, prog.args...), " ")
51 fmt.Println("Running: "+cmdline)
53 var sb strings.Builder
54 for _, prefix := range prog.prefixes {
55 err := prog.TryRunAndSave(output, sudo, prefix)
56 if err == nil {
57 return
59 sb.WriteString("\nError running '"+prefix+cmdline+"': "+err.Error()+"\n")
60 data, ferr := os.ReadFile(output)
61 if ferr != nil {
62 sb.WriteString("<failed to open log>\n")
63 } else {
64 if len(data) > 0 {
65 sb.WriteString("Program output:\n\n")
66 sb.WriteString(string(data))
71 fmt.Println("\nCould not run program: '"+cmdline+"'")
72 log.Fatal(sb.String())
75 const MAXPROMPTRETRY = 3
77 func PromptUser(prompt string, opts []string) (match string, err error) {
78 for i := 1; i < MAXPROMPTRETRY; i++ {
79 fmt.Printf("%s. (%s) Default:%s\n", prompt,
80 strings.Join(opts, "/"), opts[0])
81 var usrInput string
82 fmt.Scanln(&usrInput)
84 // Check for default entry
85 if usrInput == "" {
86 match = opts[0]
87 return
90 for _, opt := range opts {
91 if opt == usrInput {
92 match = opt
93 return
97 err = errors.New("max retries exceeded")
98 fmt.Fprintln(os.Stderr, "ERROR: max retries exceeded")
99 return
102 func AppendYesNo(yesFirst bool, yeah []string, nope []string) []string {
103 if yesFirst {
104 return append(yeah, nope...)
105 } else {
106 return append(nope, yeah...)
110 func PromptUserBool(prompt string, fallback bool) bool {
111 yeah := []string{"y", "yes"}
112 nope := []string{"n", "no"}
114 opt, err := PromptUser(prompt, AppendYesNo(fallback, yeah, nope))
115 if err != nil {
116 // Continue even if there is an error
117 return fallback
119 for _, val := range yeah {
120 if opt == val {
121 return true
124 return false
127 func MakeHDALogs(outDir string, cardName string) {
128 SysDir := "/sys/class/sound/" + cardName + "/"
129 files, _ := ioutil.ReadDir(SysDir)
130 for _, f := range files {
131 if (strings.HasPrefix(f.Name(), "hw") || strings.HasPrefix(f.Name(), "hdaudio")) && f.IsDir() {
132 in, err := os.Open(SysDir + f.Name() + "/init_pin_configs")
133 defer in.Close()
134 if err != nil {
135 log.Fatal(err)
137 out, err := os.Create(outDir + "/pin_" + strings.Replace(f.Name(), "hdaudio", "hw", -1))
138 if err != nil {
139 log.Fatal(err)
141 defer out.Close()
142 io.Copy(out, in)
146 ProcDir := "/proc/asound/" + cardName + "/"
147 files, _ = ioutil.ReadDir(ProcDir)
148 for _, f := range files {
149 if strings.HasPrefix(f.Name(), "codec#") && !f.IsDir() {
150 in, err := os.Open(ProcDir + f.Name())
151 defer in.Close()
152 if err != nil {
153 log.Fatal(err)
155 out, err := os.Create(outDir + "/" + f.Name())
156 if err != nil {
157 log.Fatal(err)
159 defer out.Close()
160 io.Copy(out, in)
165 func MakeLogs(outDir string) {
166 os.MkdirAll(outDir, 0700)
168 sudo := PromptUserBool("Should autoport use sudo to run the commands to make the logs? "+
169 "This is recommended over running autoport as root, since the generated files "+
170 "won't be owned by root. If running as root already because sudo isn't available, "+
171 "choose 'no'. Otherwise, run autoport as a regular (non-root) user and choose 'yes'.",
172 true)
174 probeGFX := PromptUserBool("WARNING: Running inteltool MAY cause your system to hang when it attempts "+
175 "to probe for graphics registers. Having the graphics registers will help create a better port. "+
176 "Should autoport probe these registers?",
177 true)
179 inteltoolArgs := "-a"
180 if probeGFX {
181 inteltoolArgs += "f"
184 var programs = []LogMakingProgram {
185 LogMakingProgram {
186 name: "lspci",
187 prefixes: []string{""},
188 args: []string{"-nnvvvxxxx"},
190 LogMakingProgram {
191 name: "dmidecode",
192 prefixes: []string{""},
193 args: []string{},
195 LogMakingProgram {
196 name: "acpidump",
197 prefixes: []string{""},
198 args: []string{},
200 LogMakingProgram {
201 name: "inteltool",
202 prefixes: []string{"../inteltool/", ""},
203 args: []string{inteltoolArgs},
205 LogMakingProgram {
206 name: "ectool",
207 prefixes: []string{"../ectool/", ""},
208 args: []string{"-pd"},
210 LogMakingProgram {
211 name: "superiotool",
212 prefixes: []string{"../superiotool/", ""},
213 args: []string{"-ade"},
217 fmt.Println("Making logs...")
218 for _, prog := range programs {
219 prog.RunAndSave(outDir, sudo)
222 SysSound := "/sys/class/sound/"
223 card := ""
224 cards, _ := ioutil.ReadDir(SysSound)
225 for _, f := range cards {
226 if strings.HasPrefix(f.Name(), "card") {
227 cid, err := ioutil.ReadFile(SysSound + f.Name() + "/id")
228 if err == nil && bytes.Equal(cid, []byte("PCH\n")) {
229 fmt.Fprintln(os.Stderr, "PCH sound card is", f.Name())
230 card = f.Name()
235 if card != "" {
236 MakeHDALogs(outDir, card)
237 } else {
238 fmt.Fprintln(os.Stderr, "HDAudio not found on PCH.")
241 for _, fname := range []string{"cpuinfo", "ioports"} {
242 in, err := os.Open("/proc/" + fname)
243 defer in.Close()
244 if err != nil {
245 log.Fatal(err)
247 out, err := os.Create(outDir + "/" + fname + ".log")
248 if err != nil {
249 log.Fatal(err)
251 defer out.Close()
252 io.Copy(out, in)
255 out, err := os.Create(outDir + "/input_bustypes.log")
256 if err != nil {
257 log.Fatal(err)
259 defer out.Close()
261 ClassInputDir := "/sys/class/input/"
262 files, _ := ioutil.ReadDir(ClassInputDir)
263 for _, f := range files {
264 if strings.HasPrefix(f.Name(), "input") && !f.Mode().IsRegular() { /* Allow both dirs and symlinks. */
265 in, err := os.Open(ClassInputDir + f.Name() + "/id/bustype")
266 defer in.Close()
267 if err != nil {
268 log.Fatal(err)
270 io.Copy(out, in)