blob: c94d182b49926ad33d2e9679fa3417999dd54d00 [file] [log] [blame]
Vladimir Serbinenko3129f792014-10-15 21:51:47 +02001package main
2
3import (
4 "bufio"
5 "flag"
6 "fmt"
7 "log"
8 "os"
9 "strconv"
10 "strings"
11)
12
13type LogDevReader struct {
14 InputDirectory string
15 ACPITables map[string][]byte
16 EC []byte
17}
18
19func isXDigit(x uint8) bool {
20 if x >= '0' && x <= '9' {
21 return true
22 }
23 if x >= 'a' && x <= 'f' {
24 return true
25 }
26 if x >= 'A' && x <= 'F' {
27 return true
28 }
29 return false
30}
31
32type HexLine struct {
33 length uint
34 values [16]byte
35 start uint
36}
37
38func (l *LogDevReader) ReadHexLine(line string) (hex HexLine) {
39 hex.start = 0
40 line = strings.Trim(line, " ")
41 fmt.Sscanf(line, "%x:", &hex.start)
42 ll, _ := fmt.Sscanf(line, "%x: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", &hex.start,
43 &hex.values[0], &hex.values[1], &hex.values[2],
44 &hex.values[3], &hex.values[4], &hex.values[5],
45 &hex.values[6], &hex.values[7], &hex.values[8],
46 &hex.values[9], &hex.values[10], &hex.values[11],
47 &hex.values[12], &hex.values[13], &hex.values[14],
48 &hex.values[15])
49 hex.length = uint(ll - 1)
50 return
51}
52
53func (l *LogDevReader) AssignHexLine(inp string, target []byte) []byte {
54 hex := l.ReadHexLine(inp)
55 if hex.start+hex.length > uint(len(target)) {
56 target = target[0 : hex.start+hex.length]
57 }
58 copy(target[hex.start:hex.start+hex.length], hex.values[0:hex.length])
59 return target
60}
61
62func (l *LogDevReader) GetEC() []byte {
63 if l.EC != nil {
64 return l.EC
65 }
66 l.EC = make([]byte, 0x100, 0x100)
67
68 file, err := os.Open(l.InputDirectory + "/ectool.log")
69 if err != nil {
70 log.Fatal(err)
71 }
72 defer file.Close()
73
74 scanner := bufio.NewScanner(file)
75
76 for scanner.Scan() {
77 line := scanner.Text()
78 if len(line) > 7 && isXDigit(line[0]) && isXDigit(line[1]) && line[2] == ':' {
79 l.EC = l.AssignHexLine(line, l.EC)
80 }
81 }
82
83 if err := scanner.Err(); err != nil {
84 log.Fatal(err)
85 }
86
87 return l.EC
88}
89
90func (l *LogDevReader) GetACPI() (Tables map[string][]byte) {
91 if l.ACPITables != nil {
92 return l.ACPITables
93 }
94 l.ACPITables = Tables
95
96 file, err := os.Open(l.InputDirectory + "/acpidump.log")
97 if err != nil {
98 log.Fatal(err)
99 }
100 defer file.Close()
101
102 scanner := bufio.NewScanner(file)
103
104 Tables = map[string][]byte{}
105
106 curTable := ""
107 for scanner.Scan() {
108 line := scanner.Text()
109 switch {
110 case len(line) >= 6 && line[5] == '@':
111 curTable = line[0:4]
112 Tables[curTable] = make([]byte, 0, 100000)
113 case len(line) > 7 && line[0:2] == " " && isXDigit(line[2]) && isXDigit(line[3]) && isXDigit(line[4]) && isXDigit(line[5]) && line[6] == ':':
114 Tables[curTable] = l.AssignHexLine(line, Tables[curTable])
115 }
116 }
117
118 if err := scanner.Err(); err != nil {
119 log.Fatal(err)
120 }
121
122 return
123}
124
125func (l *LogDevReader) GetPCIList() (PCIList []PCIDevData) {
126 file, err := os.Open(l.InputDirectory + "/lspci.log")
127 if err != nil {
128 log.Fatal(err)
129 }
130 defer file.Close()
131
132 scanner := bufio.NewScanner(file)
133
134 PCIList = []PCIDevData{}
135
136 for scanner.Scan() {
137 line := scanner.Text()
138 switch {
139 case !(len(line) < 7 || !isXDigit(line[0]) || !isXDigit(line[1]) || line[2] != ':' || !isXDigit(line[3]) || !isXDigit(line[4]) || line[5] != '.' || !isXDigit(line[6])):
140 cur := PCIDevData{}
141 fmt.Sscanf(line, "%x:%x.%x", &cur.Bus, &cur.Dev, &cur.Func)
142 lc := strings.LastIndex(line, ":")
143 li := strings.LastIndex(line[0:lc], "[")
144 if li < 0 {
145 continue
146 }
147 ven := 0
148 dev := 0
149 fmt.Sscanf(line[li+1:], "%x:%x", &ven, &dev)
150 cur.PCIDevID = uint16(dev)
151 cur.PCIVenID = uint16(ven)
152 cur.ConfigDump = make([]byte, 0x100, 0x1000)
153 PCIList = append(PCIList, cur)
154 case len(line) > 7 && isXDigit(line[0]) && line[1] == '0' && line[2] == ':':
155 start := 0
156 fmt.Sscanf(line, "%x:", &start)
157 cur := &PCIList[len(PCIList)-1]
158 cur.ConfigDump = l.AssignHexLine(line, cur.ConfigDump)
159 }
160 }
161
162 if err := scanner.Err(); err != nil {
163 log.Fatal(err)
164 }
165
166 return
167}
168
169func (l *LogDevReader) GetInteltool() (ret InteltoolData) {
170 file, err := os.Open(l.InputDirectory + "/inteltool.log")
171 if err != nil {
172 log.Fatal(err)
173 }
174 defer file.Close()
175
176 scanner := bufio.NewScanner(file)
177 paragraph := ""
178 ret.GPIO = map[uint16]uint32{}
179 ret.RCBA = map[uint16]uint32{}
180 ret.IGD = map[uint32]uint32{}
181 for scanner.Scan() {
182 line := scanner.Text()
183 switch {
184 case len(line) > 7 && line[0] == '0' && line[1] == 'x' && line[6] == ':' && paragraph == "RCBA":
185 addr, value := 0, 0
186 fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
187 ret.RCBA[uint16(addr)] = uint32(value)
188 case len(line) > 9 && line[0] == '0' && line[1] == 'x' && line[8] == ':' && paragraph == "IGD":
189 addr, value := 0, 0
190 fmt.Sscanf(line, "0x%x: 0x%x", &addr, &value)
191 ret.IGD[uint32(addr)] = uint32(value)
192 case strings.Contains(line, "DEFAULT"):
193 continue
194 case strings.Contains(line, "DIFF"):
195 continue
196 case strings.HasPrefix(line, "gpiobase"):
197 addr, value := 0, 0
198 fmt.Sscanf(line, "gpiobase+0x%x: 0x%x", &addr, &value)
199 ret.GPIO[uint16(addr)] = uint32(value)
200 case strings.HasPrefix(line, "============="):
201 paragraph = strings.Trim(line, "= ")
202 }
203 }
204
205 if err := scanner.Err(); err != nil {
206 log.Fatal(err)
207 }
208 return
209}
210
211func (l *LogDevReader) GetDMI() (ret DMIData) {
212 file, err := os.Open(l.InputDirectory + "/dmidecode.log")
213 if err != nil {
214 log.Fatal(err)
215 }
216 defer file.Close()
217
218 scanner := bufio.NewScanner(file)
219 paragraph := ""
220 for scanner.Scan() {
221 line := scanner.Text()
222 if !strings.HasPrefix(line, "\t") {
223 paragraph = strings.TrimSpace(line)
224 continue
225 }
226 idx := strings.Index(line, ":")
227 if idx < 0 {
228 continue
229 }
230 name := strings.TrimSpace(line[0:idx])
231 value := strings.TrimSpace(line[idx+1:])
232 switch paragraph + ":" + name {
233 case "System Information:Manufacturer":
234 ret.Vendor = value
235 case "System Information:Product Name":
236 ret.Model = value
237 case "System Information:Version":
238 ret.Version = value
239 case "Chassis Information:Type":
240 ret.IsLaptop = (value == "Notebook" || value == "Laptop")
241 }
242 }
243
244 if err := scanner.Err(); err != nil {
245 log.Fatal(err)
246 }
247 return
248}
249
250func (l *LogDevReader) GetAzaliaCodecs() (ret []AzaliaCodec) {
251 for codecno := 0; codecno < 10; codecno++ {
252 cur := AzaliaCodec{CodecNo: codecno, PinConfig: map[int]uint32{}}
253 codec, err := os.Open(l.InputDirectory + "/codec#" + strconv.Itoa(codecno))
254 if err != nil {
255 continue
256 }
257 defer codec.Close()
258 pin, err := os.Open(l.InputDirectory + "/pin_hwC0D" + strconv.Itoa(codecno))
259 if err != nil {
260 continue
261 }
262 defer pin.Close()
263
264 scanner := bufio.NewScanner(codec)
265 for scanner.Scan() {
266 line := scanner.Text()
267 if strings.HasPrefix(line, "Codec:") {
268 fmt.Sscanf(line, "Codec: %s", &cur.Name)
269 continue
270 }
271 if strings.HasPrefix(line, "Vendor Id:") {
272 fmt.Sscanf(line, "Vendor Id: 0x%x", &cur.VendorID)
273 continue
274 }
275 if strings.HasPrefix(line, "Subsystem Id:") {
276 fmt.Sscanf(line, "Subsystem Id: 0x%x", &cur.SubsystemID)
277 continue
278 }
279 }
280
281 scanner = bufio.NewScanner(pin)
282 for scanner.Scan() {
283 line := scanner.Text()
284 addr := 0
285 val := uint32(0)
286 fmt.Sscanf(line, "0x%x 0x%x", &addr, &val)
287 cur.PinConfig[addr] = val
288 }
289 ret = append(ret, cur)
290 }
291 return
292}
293
294func (l *LogDevReader) GetIOPorts() []IOPorts {
295 file, err := os.Open(l.InputDirectory + "/ioports.log")
296 if err != nil {
297 log.Fatal(err)
298 }
299 defer file.Close()
300 scanner := bufio.NewScanner(file)
301 ret := make([]IOPorts, 0, 100)
302 for scanner.Scan() {
303 line := scanner.Text()
304 el := IOPorts{}
305 fmt.Sscanf(line, " %x-%x : %s", &el.Start, &el.End, &el.Usage)
306 ret = append(ret, el)
307 }
308
309 if err := scanner.Err(); err != nil {
310 log.Fatal(err)
311 }
312 return ret
313
314}
315
316func (l *LogDevReader) GetCPUModel() (ret []uint32) {
317 file, err := os.Open(l.InputDirectory + "/cpuinfo.log")
318 if err != nil {
319 log.Fatal(err)
320 }
321 defer file.Close()
322
323 scanner := bufio.NewScanner(file)
324 ret = make([]uint32, 0, 100)
325 proc := 0
326 for scanner.Scan() {
327 line := scanner.Text()
328 sep := strings.Index(line, ":")
329 if sep < 0 {
330 continue
331 }
332 key := strings.TrimSpace(line[0:sep])
333 val := strings.TrimSpace(line[sep+1:])
334
335 if key == "processor" {
336 proc, _ := strconv.Atoi(val)
337 if len(ret) <= proc {
338 ret = ret[0 : proc+1]
339 }
340 continue
341 }
342 if key == "cpu family" {
343 family, _ := strconv.Atoi(val)
344 ret[proc] |= uint32(((family & 0xf) << 8) | ((family & 0xff0) << 16))
345 }
346 if key == "model" {
347 model, _ := strconv.Atoi(val)
348 ret[proc] |= uint32(((model & 0xf) << 4) | ((model & 0xf0) << 12))
349 }
350 if key == "stepping" {
351 stepping, _ := strconv.Atoi(val)
352 ret[proc] |= uint32(stepping & 0xf)
353 }
354 }
355
356 if err := scanner.Err(); err != nil {
357 log.Fatal(err)
358 }
359 return
360}
361
Vladimir Serbinenko91195c62015-05-29 23:53:37 +0200362func (l *LogDevReader) HasPS2() bool {
363 file, err := os.Open(l.InputDirectory + "/input_bustypes.log")
364 if err != nil {
365 log.Fatal(err)
366 }
367 defer file.Close()
368 scanner := bufio.NewScanner(file)
369 for scanner.Scan() {
370 line := scanner.Text()
371 if strings.Index(line, "0011") >= 0 {
372 return true
373 }
374 }
375 return false
376}
377
Vladimir Serbinenko3129f792014-10-15 21:51:47 +0200378var FlagLogInput = flag.String("input_log", ".", "Input log directory")
379var FlagLogMkLogs = flag.Bool("make_logs", false, "Dump logs")
380
381func MakeLogReader() *LogDevReader {
382 if *FlagLogMkLogs {
383 MakeLogs(*FlagLogInput)
384 }
385 return &LogDevReader{InputDirectory: *FlagLogInput}
386}