log_reader.go 9.8 KB

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