xref: /openbmc/openbmc-tools/dbus-vis/ipmi_parse.js (revision b65280ff745c47dbb1e668e68e156bf3de6b6e93)
1*b65280ffSSui Chen// This file parses ASCII text-encoded dbus message dump.
2*b65280ffSSui Chen
3*b65280ffSSui Chenfunction extractUsec(line) {
4*b65280ffSSui Chen  let i0 = line.indexOf('time=');
5*b65280ffSSui Chen  if (i0 == -1) {
6*b65280ffSSui Chen    return BigInt(-1);
7*b65280ffSSui Chen  }
8*b65280ffSSui Chen  let line1 = line.substr(i0);
9*b65280ffSSui Chen  let i1 = line1.indexOf(' ');
10*b65280ffSSui Chen  if (i1 == -1) {
11*b65280ffSSui Chen    return BigInt(-1);
12*b65280ffSSui Chen  }
13*b65280ffSSui Chen  let line2 = line1.substr(5, i1 - 5);
14*b65280ffSSui Chen  let sp = line2.split('.');
15*b65280ffSSui Chen  return BigInt(sp[0]) * BigInt(1000000) + BigInt(sp[1]);
16*b65280ffSSui Chen}
17*b65280ffSSui Chen
18*b65280ffSSui Chenfunction extractInt(line, kw) {
19*b65280ffSSui Chen  let N = kw.length;
20*b65280ffSSui Chen  let i0 = line.indexOf(kw);
21*b65280ffSSui Chen  if (i0 == -1) {
22*b65280ffSSui Chen    return null;
23*b65280ffSSui Chen  }
24*b65280ffSSui Chen  let line1 = line.substr(i0);
25*b65280ffSSui Chen  let i1 = line1.indexOf(' ');
26*b65280ffSSui Chen  if (i1 == -1) {
27*b65280ffSSui Chen    i1 = line.length;
28*b65280ffSSui Chen  }
29*b65280ffSSui Chen  let line2 = line1.substr(N, i1 - N);
30*b65280ffSSui Chen  return parseInt(line2);
31*b65280ffSSui Chen}
32*b65280ffSSui Chen
33*b65280ffSSui Chenfunction extractSerial(line) {
34*b65280ffSSui Chen  return extractInt(line, 'serial=');
35*b65280ffSSui Chen}
36*b65280ffSSui Chen
37*b65280ffSSui Chenfunction extractReplySerial(line) {
38*b65280ffSSui Chen  return extractInt(line, 'reply_serial=');
39*b65280ffSSui Chen}
40*b65280ffSSui Chen
41*b65280ffSSui Chen// Returns [byte, i+1] if successful
42*b65280ffSSui Chen// Returns [null, i  ] if unsuccessful
43*b65280ffSSui Chenfunction munchByte(lines, i) {
44*b65280ffSSui Chen  if (i >= lines.length) {
45*b65280ffSSui Chen    return [null, i]
46*b65280ffSSui Chen  }
47*b65280ffSSui Chen  let l = lines[i];
48*b65280ffSSui Chen  let idx = l.indexOf('byte');
49*b65280ffSSui Chen  if (idx != -1) {
50*b65280ffSSui Chen    return [parseInt(l.substr(idx + 4), 10), i + 1];
51*b65280ffSSui Chen  } else {
52*b65280ffSSui Chen    return [null, i];
53*b65280ffSSui Chen  }
54*b65280ffSSui Chen}
55*b65280ffSSui Chen
56*b65280ffSSui Chen// array of bytes "@"
57*b65280ffSSui Chenfunction munchArrayOfBytes1(lines, i) {
58*b65280ffSSui Chen  let l = lines[i];
59*b65280ffSSui Chen  let idx = l.indexOf('array of bytes "');
60*b65280ffSSui Chen  if (idx != -1) {
61*b65280ffSSui Chen    let the_ch = l.substr(idx + 16, 1);
62*b65280ffSSui Chen    return [[the_ch.charCodeAt(0)], i + 1];
63*b65280ffSSui Chen  } else {
64*b65280ffSSui Chen    return [null, i];
65*b65280ffSSui Chen  }
66*b65280ffSSui Chen}
67*b65280ffSSui Chen
68*b65280ffSSui Chenfunction munchArrayOfBytes2(lines, i) {
69*b65280ffSSui Chen  let l = lines[i];
70*b65280ffSSui Chen  let idx = l.indexOf('array of bytes [');
71*b65280ffSSui Chen  if (idx == -1) {
72*b65280ffSSui Chen    idx = l.indexOf('array [');
73*b65280ffSSui Chen  }
74*b65280ffSSui Chen  if (idx != -1) {
75*b65280ffSSui Chen    let j = i + 1;
76*b65280ffSSui Chen    let payload = [];
77*b65280ffSSui Chen    while (true) {
78*b65280ffSSui Chen      if (j >= lines.length) {
79*b65280ffSSui Chen        break;
80*b65280ffSSui Chen      }
81*b65280ffSSui Chen      l = lines[j];
82*b65280ffSSui Chen      let sp = l.trim().split(' ');
83*b65280ffSSui Chen      let ok = true;
84*b65280ffSSui Chen      for (let k = 0; k < sp.length; k++) {
85*b65280ffSSui Chen        let b = parseInt(sp[k], 16);
86*b65280ffSSui Chen        if (isNaN(b)) {
87*b65280ffSSui Chen          ok = false;
88*b65280ffSSui Chen          break;
89*b65280ffSSui Chen        } else {
90*b65280ffSSui Chen          payload.push(b);
91*b65280ffSSui Chen        }
92*b65280ffSSui Chen      }
93*b65280ffSSui Chen      if (!ok) {
94*b65280ffSSui Chen        j--;
95*b65280ffSSui Chen        break;
96*b65280ffSSui Chen      } else
97*b65280ffSSui Chen        j++;
98*b65280ffSSui Chen    }
99*b65280ffSSui Chen    return [payload, j];
100*b65280ffSSui Chen  } else {
101*b65280ffSSui Chen    return [null, i];
102*b65280ffSSui Chen  }
103*b65280ffSSui Chen}
104*b65280ffSSui Chen
105*b65280ffSSui Chenfunction munchArrayOfBytes(lines, i) {
106*b65280ffSSui Chen  if (i >= lines.length) return [null, i];
107*b65280ffSSui Chen
108*b65280ffSSui Chen  let x = munchArrayOfBytes1(lines, i);
109*b65280ffSSui Chen  if (x[0] != null) {
110*b65280ffSSui Chen    return x;
111*b65280ffSSui Chen  }
112*b65280ffSSui Chen  x = munchArrayOfBytes2(lines, i);
113*b65280ffSSui Chen  if (x[0] != null) {
114*b65280ffSSui Chen    return x;
115*b65280ffSSui Chen  }
116*b65280ffSSui Chen  return [null, i];
117*b65280ffSSui Chen}
118*b65280ffSSui Chen
119*b65280ffSSui Chen// ReceivedMessage
120*b65280ffSSui Chenfunction munchLegacyMessageStart(lines, i) {
121*b65280ffSSui Chen  let entry = {
122*b65280ffSSui Chen    netfn: 0,
123*b65280ffSSui Chen    lun: 0,
124*b65280ffSSui Chen    cmd: 0,
125*b65280ffSSui Chen    serial: 0,
126*b65280ffSSui Chen    start_usec: 0,
127*b65280ffSSui Chen    end_usec: 0,
128*b65280ffSSui Chen    request: [],
129*b65280ffSSui Chen    response: []
130*b65280ffSSui Chen  };
131*b65280ffSSui Chen
132*b65280ffSSui Chen  let ts = extractUsec(lines[i]);
133*b65280ffSSui Chen  entry.start_usec = ts;
134*b65280ffSSui Chen
135*b65280ffSSui Chen  let x = munchByte(lines, i + 1);
136*b65280ffSSui Chen  if (x[0] == null) {
137*b65280ffSSui Chen    return [null, i];
138*b65280ffSSui Chen  }
139*b65280ffSSui Chen  entry.serial = x[0];
140*b65280ffSSui Chen  let j = x[1];
141*b65280ffSSui Chen
142*b65280ffSSui Chen  x = munchByte(lines, j);
143*b65280ffSSui Chen  if (x[0] == null) {
144*b65280ffSSui Chen    return [null, i];
145*b65280ffSSui Chen  }
146*b65280ffSSui Chen  entry.netfn = x[0];
147*b65280ffSSui Chen  j = x[1];
148*b65280ffSSui Chen
149*b65280ffSSui Chen  x = munchByte(lines, j);
150*b65280ffSSui Chen  if (x[0] == null) {
151*b65280ffSSui Chen    return [null, i];
152*b65280ffSSui Chen  }
153*b65280ffSSui Chen  entry.lun = x[0];
154*b65280ffSSui Chen  j = x[1];
155*b65280ffSSui Chen
156*b65280ffSSui Chen  x = munchByte(lines, j);
157*b65280ffSSui Chen  if (x[0] == null) {
158*b65280ffSSui Chen    return [null, i];
159*b65280ffSSui Chen  }
160*b65280ffSSui Chen  entry.cmd = x[0];
161*b65280ffSSui Chen  j = x[1];
162*b65280ffSSui Chen
163*b65280ffSSui Chen  x = munchArrayOfBytes(lines, j);
164*b65280ffSSui Chen  if (x[0] == null) {
165*b65280ffSSui Chen    return [null, i];
166*b65280ffSSui Chen  }
167*b65280ffSSui Chen  entry.request = x[0];
168*b65280ffSSui Chen  j = x[1];
169*b65280ffSSui Chen
170*b65280ffSSui Chen  return [entry, j];
171*b65280ffSSui Chen}
172*b65280ffSSui Chen
173*b65280ffSSui Chenfunction munchLegacyMessageEnd(lines, i, in_flight, parsed_entries) {
174*b65280ffSSui Chen  let ts = extractUsec(lines[i]);
175*b65280ffSSui Chen
176*b65280ffSSui Chen  let x = munchByte(lines, i + 1);
177*b65280ffSSui Chen  if (x[0] == null) {
178*b65280ffSSui Chen    return [null, i];
179*b65280ffSSui Chen  }  // serial
180*b65280ffSSui Chen  let serial = x[0];
181*b65280ffSSui Chen  let j = x[1];
182*b65280ffSSui Chen
183*b65280ffSSui Chen  let entry = null;
184*b65280ffSSui Chen  if (serial in in_flight) {
185*b65280ffSSui Chen    entry = in_flight[serial];
186*b65280ffSSui Chen    delete in_flight[serial];
187*b65280ffSSui Chen  } else {
188*b65280ffSSui Chen    return [null, i];
189*b65280ffSSui Chen  }
190*b65280ffSSui Chen
191*b65280ffSSui Chen  entry.end_usec = ts;
192*b65280ffSSui Chen
193*b65280ffSSui Chen  x = munchByte(lines, j);  // netfn
194*b65280ffSSui Chen  if (x[0] == null) {
195*b65280ffSSui Chen    return [null, i];
196*b65280ffSSui Chen  }
197*b65280ffSSui Chen  if (entry.netfn + 1 == x[0]) {
198*b65280ffSSui Chen  } else {
199*b65280ffSSui Chen    return [null, i];
200*b65280ffSSui Chen  }
201*b65280ffSSui Chen  j = x[1];
202*b65280ffSSui Chen
203*b65280ffSSui Chen  x = munchByte(lines, j);  // lun (not used right now)
204*b65280ffSSui Chen  if (x[0] == null) {
205*b65280ffSSui Chen    return [null, i];
206*b65280ffSSui Chen  }
207*b65280ffSSui Chen  j = x[1];
208*b65280ffSSui Chen
209*b65280ffSSui Chen  x = munchByte(lines, j);  // cmd
210*b65280ffSSui Chen  if (x[0] == null) {
211*b65280ffSSui Chen    return [null, i];
212*b65280ffSSui Chen  }
213*b65280ffSSui Chen  if (entry.cmd == x[0]) {
214*b65280ffSSui Chen  } else {
215*b65280ffSSui Chen    return [null, i];
216*b65280ffSSui Chen  }
217*b65280ffSSui Chen  j = x[1];
218*b65280ffSSui Chen
219*b65280ffSSui Chen  x = munchByte(lines, j);  // cc
220*b65280ffSSui Chen  if (x[0] == null) {
221*b65280ffSSui Chen    return [null, i];
222*b65280ffSSui Chen  }
223*b65280ffSSui Chen  j = x[1];
224*b65280ffSSui Chen
225*b65280ffSSui Chen  x = munchArrayOfBytes(lines, j);
226*b65280ffSSui Chen  if (x[0] == null) {
227*b65280ffSSui Chen    entry.response = [];
228*b65280ffSSui Chen  } else {
229*b65280ffSSui Chen    entry.response = x[0];
230*b65280ffSSui Chen  }
231*b65280ffSSui Chen  j = x[1];
232*b65280ffSSui Chen
233*b65280ffSSui Chen  parsed_entries.push(entry);
234*b65280ffSSui Chen
235*b65280ffSSui Chen  return [entry, j];
236*b65280ffSSui Chen}
237*b65280ffSSui Chen
238*b65280ffSSui Chenfunction munchNewMessageStart(lines, i, in_flight) {
239*b65280ffSSui Chen  let ts = extractUsec(lines[i]);
240*b65280ffSSui Chen  let serial = extractSerial(lines[i]);
241*b65280ffSSui Chen
242*b65280ffSSui Chen  let entry = {
243*b65280ffSSui Chen    netfn: 0,
244*b65280ffSSui Chen    lun: 0,
245*b65280ffSSui Chen    cmd: 0,
246*b65280ffSSui Chen    serial: -999,
247*b65280ffSSui Chen    start_usec: 0,
248*b65280ffSSui Chen    end_usec: 0,
249*b65280ffSSui Chen    request: [],
250*b65280ffSSui Chen    response: []
251*b65280ffSSui Chen  };
252*b65280ffSSui Chen  entry.start_usec = ts;
253*b65280ffSSui Chen  entry.serial = serial;
254*b65280ffSSui Chen
255*b65280ffSSui Chen  let x = munchByte(lines, i + 1);
256*b65280ffSSui Chen  if (x[0] == null) {
257*b65280ffSSui Chen    return [null, i];
258*b65280ffSSui Chen  }
259*b65280ffSSui Chen  entry.netfn = x[0];
260*b65280ffSSui Chen  let j = x[1];
261*b65280ffSSui Chen
262*b65280ffSSui Chen  x = munchByte(lines, j);
263*b65280ffSSui Chen  if (x[0] == null) {
264*b65280ffSSui Chen    return [null, i];
265*b65280ffSSui Chen  }
266*b65280ffSSui Chen  entry.lun = x[0];
267*b65280ffSSui Chen  j = x[1];
268*b65280ffSSui Chen
269*b65280ffSSui Chen  x = munchByte(lines, j);
270*b65280ffSSui Chen  if (x[0] == null) {
271*b65280ffSSui Chen    return [null, i];
272*b65280ffSSui Chen  }
273*b65280ffSSui Chen  entry.cmd = x[0];
274*b65280ffSSui Chen  j = x[1];
275*b65280ffSSui Chen
276*b65280ffSSui Chen  x = munchArrayOfBytes(lines, j);
277*b65280ffSSui Chen  if (x[0] == null) {
278*b65280ffSSui Chen    entry.request = [];
279*b65280ffSSui Chen  }  // Truncated
280*b65280ffSSui Chen  entry.request = x[0];
281*b65280ffSSui Chen  j = x[1];
282*b65280ffSSui Chen
283*b65280ffSSui Chen  return [entry, j];
284*b65280ffSSui Chen}
285*b65280ffSSui Chen
286*b65280ffSSui Chenfunction munchNewMessageEnd(lines, i, in_flight, parsed_entries) {
287*b65280ffSSui Chen  let ts = extractUsec(lines[i]);
288*b65280ffSSui Chen  let reply_serial = extractReplySerial(lines[i]);
289*b65280ffSSui Chen
290*b65280ffSSui Chen  let entry = null;
291*b65280ffSSui Chen  if (reply_serial in in_flight) {
292*b65280ffSSui Chen    entry = in_flight[reply_serial];
293*b65280ffSSui Chen    delete in_flight[reply_serial];
294*b65280ffSSui Chen  } else {
295*b65280ffSSui Chen    return [null, i];
296*b65280ffSSui Chen  }
297*b65280ffSSui Chen
298*b65280ffSSui Chen  entry.end_usec = ts;
299*b65280ffSSui Chen
300*b65280ffSSui Chen  let x = munchByte(lines, i + 2);  // Skip "struct {"
301*b65280ffSSui Chen  if (x[0] == null) {
302*b65280ffSSui Chen    return [null, i];
303*b65280ffSSui Chen  }  // NetFN
304*b65280ffSSui Chen  if (entry.netfn + 1 != x[0]) {
305*b65280ffSSui Chen    return [null, i];
306*b65280ffSSui Chen  }
307*b65280ffSSui Chen  let j = x[1];
308*b65280ffSSui Chen
309*b65280ffSSui Chen  x = munchByte(lines, j);  // LUN
310*b65280ffSSui Chen  if (x[0] == null) {
311*b65280ffSSui Chen    return [null, i];
312*b65280ffSSui Chen  }
313*b65280ffSSui Chen  j = x[1];
314*b65280ffSSui Chen
315*b65280ffSSui Chen  x = munchByte(lines, j);  // CMD
316*b65280ffSSui Chen  if (x[0] == null) {
317*b65280ffSSui Chen    return [null, i];
318*b65280ffSSui Chen  }
319*b65280ffSSui Chen  if (entry.cmd != x[0]) {
320*b65280ffSSui Chen    return [null, i];
321*b65280ffSSui Chen  }
322*b65280ffSSui Chen  j = x[1];
323*b65280ffSSui Chen
324*b65280ffSSui Chen  x = munchByte(lines, j);  // cc
325*b65280ffSSui Chen  if (x[0] == null) {
326*b65280ffSSui Chen    return [null, i];
327*b65280ffSSui Chen  }
328*b65280ffSSui Chen  j = x[1];
329*b65280ffSSui Chen
330*b65280ffSSui Chen  x = munchArrayOfBytes(lines, j);
331*b65280ffSSui Chen  if (x[0] == null) {
332*b65280ffSSui Chen    entry.response = [];
333*b65280ffSSui Chen  } else {
334*b65280ffSSui Chen    entry.response = x[0];
335*b65280ffSSui Chen  }
336*b65280ffSSui Chen  j = x[1];
337*b65280ffSSui Chen
338*b65280ffSSui Chen  parsed_entries.push(entry);
339*b65280ffSSui Chen
340*b65280ffSSui Chen  return [entry, j];
341*b65280ffSSui Chen}
342*b65280ffSSui Chen
343*b65280ffSSui Chen// Parsing state
344*b65280ffSSui Chenlet g_ipmi_parse_buf = '';
345*b65280ffSSui Chenlet g_ipmi_parse_lines = [];
346*b65280ffSSui Chenlet g_ipmi_in_flight = {};
347*b65280ffSSui Chenlet g_ipmi_parsed_entries = [];
348*b65280ffSSui Chenfunction StartParseIPMIDump() {
349*b65280ffSSui Chen  g_ipmi_parse_lines = [];
350*b65280ffSSui Chen  g_ipmi_parsed_entries = [];
351*b65280ffSSui Chen  g_ipmi_in_flight = {};
352*b65280ffSSui Chen  g_ipmi_parse_buf = '';
353*b65280ffSSui Chen}
354*b65280ffSSui Chenfunction AppendToParseBuffer(x) {
355*b65280ffSSui Chen  g_ipmi_parse_buf += x;
356*b65280ffSSui Chen}
357*b65280ffSSui Chenfunction MunchLines() {
358*b65280ffSSui Chen  // 1. Extract all lines from the buffer
359*b65280ffSSui Chen  let chars_munched = 0;
360*b65280ffSSui Chen  while (true) {
361*b65280ffSSui Chen    let idx = g_ipmi_parse_buf.indexOf('\n');
362*b65280ffSSui Chen    if (idx == -1) break;
363*b65280ffSSui Chen    let l = g_ipmi_parse_buf.substr(0, idx);
364*b65280ffSSui Chen    g_ipmi_parse_lines.push(l);
365*b65280ffSSui Chen    g_ipmi_parse_buf = g_ipmi_parse_buf.substr(idx + 1);
366*b65280ffSSui Chen    chars_munched += (idx + 1);
367*b65280ffSSui Chen  }
368*b65280ffSSui Chen  console.log(chars_munched + ' chars munched');
369*b65280ffSSui Chen
370*b65280ffSSui Chen  // 2. Parse as many lines as possible
371*b65280ffSSui Chen  let lidx_last = 0;
372*b65280ffSSui Chen  let i = 0;
373*b65280ffSSui Chen  while (i < g_ipmi_parse_lines.length) {
374*b65280ffSSui Chen    let line = g_ipmi_parse_lines[i];
375*b65280ffSSui Chen    if (line.indexOf('interface=org.openbmc.HostIpmi') != -1 &&
376*b65280ffSSui Chen        line.indexOf('member=ReceivedMessage') != -1) {
377*b65280ffSSui Chen      let x = munchLegacyMessageStart(g_ipmi_parse_lines, i);
378*b65280ffSSui Chen      let entry = x[0];
379*b65280ffSSui Chen      if (i != x[1]) lidx_last = x[1];  // Munch success!
380*b65280ffSSui Chen      i = x[1];
381*b65280ffSSui Chen      if (entry != null) {
382*b65280ffSSui Chen        g_ipmi_in_flight[entry.serial] = entry;
383*b65280ffSSui Chen      }
384*b65280ffSSui Chen    } else if (
385*b65280ffSSui Chen        line.indexOf('interface=org.openbmc.HostIpmi') != -1 &&
386*b65280ffSSui Chen        line.indexOf('member=sendMessage') != -1) {
387*b65280ffSSui Chen      let x = munchLegacyMessageEnd(
388*b65280ffSSui Chen          g_ipmi_parse_lines, i, g_ipmi_in_flight, g_ipmi_parsed_entries);
389*b65280ffSSui Chen      if (i != x[1]) lidx_last = x[1];  // Munch success!
390*b65280ffSSui Chen      i = x[1];
391*b65280ffSSui Chen
392*b65280ffSSui Chen    } else if (
393*b65280ffSSui Chen        line.indexOf('interface=xyz.openbmc_project.Ipmi.Server') != -1 &&
394*b65280ffSSui Chen        line.indexOf('member=execute') != -1) {
395*b65280ffSSui Chen      let x = munchNewMessageStart(g_ipmi_parse_lines, i);
396*b65280ffSSui Chen      let entry = x[0];
397*b65280ffSSui Chen      if (i != x[1]) lidx_last = x[1];
398*b65280ffSSui Chen      i = x[1];
399*b65280ffSSui Chen      if (entry != null) {
400*b65280ffSSui Chen        g_ipmi_in_flight[entry.serial] = entry;
401*b65280ffSSui Chen      }
402*b65280ffSSui Chen    } else if (line.indexOf('method return') != -1) {
403*b65280ffSSui Chen      let x = munchNewMessageEnd(
404*b65280ffSSui Chen          g_ipmi_parse_lines, i, g_ipmi_in_flight, g_ipmi_parsed_entries);
405*b65280ffSSui Chen      if (i != x[1]) lidx_last = x[1];  // Munch success
406*b65280ffSSui Chen      i = x[1];
407*b65280ffSSui Chen    }
408*b65280ffSSui Chen    i++;
409*b65280ffSSui Chen  }
410*b65280ffSSui Chen  g_ipmi_parse_lines = g_ipmi_parse_lines.slice(
411*b65280ffSSui Chen      lidx_last,
412*b65280ffSSui Chen      g_ipmi_parse_lines.length);  // Remove munched lines
413*b65280ffSSui Chen  console.log(
414*b65280ffSSui Chen      lidx_last + ' lines munched, |lines|=' + g_ipmi_parse_lines.length +
415*b65280ffSSui Chen          ', |entries|=' + g_ipmi_parsed_entries.length,
416*b65280ffSSui Chen      ', |inflight|=' + Object.keys(g_ipmi_in_flight).length);
417*b65280ffSSui Chen}
418*b65280ffSSui Chen
419*b65280ffSSui Chenlet last_update_time = 0;  // Millis since Unix Epoch
420*b65280ffSSui Chenfunction UpdateLayout(level) {
421*b65280ffSSui Chen  const this_update_time = new Date().getTime();
422*b65280ffSSui Chen  const over_1s = (this_update_time - last_update_time > 1000);
423*b65280ffSSui Chen  if (!over_1s) {
424*b65280ffSSui Chen    if (level > 0) {
425*b65280ffSSui Chen      setTimeout(function() {
426*b65280ffSSui Chen        UpdateLayout(level - 1);
427*b65280ffSSui Chen      }, 1000);
428*b65280ffSSui Chen    } else {
429*b65280ffSSui Chen      return;
430*b65280ffSSui Chen    }
431*b65280ffSSui Chen  }
432*b65280ffSSui Chen
433*b65280ffSSui Chen  if (g_ipmi_parsed_entries.length > 0) {
434*b65280ffSSui Chen    last_update_time = this_update_time;
435*b65280ffSSui Chen    // Write to Data_IPMI
436*b65280ffSSui Chen    let ts0 = g_ipmi_parsed_entries[0].start_usec;
437*b65280ffSSui Chen    let ts1 = g_ipmi_parsed_entries[g_ipmi_parsed_entries.length - 1].end_usec;
438*b65280ffSSui Chen
439*b65280ffSSui Chen    // When calling from DBus PCap loader, the following happens
440*b65280ffSSui Chen    // >> OnGroupByConditionChanged
441*b65280ffSSui Chen    //   >> Preprocess  <-- Time shift will happen here
442*b65280ffSSui Chen    // So, we don't do time-shifting here
443*b65280ffSSui Chen    let time_shift;
444*b65280ffSSui Chen    if (g_StartingSec != undefined) {
445*b65280ffSSui Chen      time_shift = BigInt(0);
446*b65280ffSSui Chen    } else {  // This is during live capture mode
447*b65280ffSSui Chen      time_shift = ts0;
448*b65280ffSSui Chen    }
449*b65280ffSSui Chen
450*b65280ffSSui Chen    Data_IPMI = [];
451*b65280ffSSui Chen    for (i = 0; i < g_ipmi_parsed_entries.length; i++) {
452*b65280ffSSui Chen      let entry = g_ipmi_parsed_entries[i];
453*b65280ffSSui Chen      let x = [
454*b65280ffSSui Chen        entry.netfn, entry.cmd, parseInt(entry.start_usec - time_shift),
455*b65280ffSSui Chen        parseInt(entry.end_usec - time_shift), entry.request, entry.response
456*b65280ffSSui Chen      ];
457*b65280ffSSui Chen      Data_IPMI.push(x);
458*b65280ffSSui Chen    }
459*b65280ffSSui Chen
460*b65280ffSSui Chen    // Re-calculate time range
461*b65280ffSSui Chen    RANGE_LEFT_INIT = 0;
462*b65280ffSSui Chen    RANGE_RIGHT_INIT =
463*b65280ffSSui Chen        parseInt((ts1 - ts0) / BigInt(1000000) / BigInt(10)) * 10 + 10;
464*b65280ffSSui Chen
465*b65280ffSSui Chen    IsCanvasDirty = true;
466*b65280ffSSui Chen    OnGroupByConditionChanged();
467*b65280ffSSui Chen
468*b65280ffSSui Chen    ComputeHistogram();
469*b65280ffSSui Chen  } else {
470*b65280ffSSui Chen    console.log('No entries parsed');
471*b65280ffSSui Chen  }
472*b65280ffSSui Chen}
473*b65280ffSSui Chen
474*b65280ffSSui Chenfunction ParseIPMIDump(data) {
475*b65280ffSSui Chen  StartParseIPMIDump();
476*b65280ffSSui Chen  AppendToParseBuffer(data);
477*b65280ffSSui Chen  MunchLines();
478*b65280ffSSui Chen  UpdateLayout();
479*b65280ffSSui Chen}
480