blob: 472d4ae44046544abd5d0f651c6572502e5f937a [file] [log] [blame]
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001/*
2 * Copyright (c) 2018-present Facebook. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Karthikeyan Pasupathi813f2932022-04-06 14:10:48 +053017#include <usb-dbg.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080018
19namespace ipmi
20{
21
Vijay Khemka63c99be2020-05-27 19:14:35 -070022ipmi_ret_t getNetworkData(uint8_t lan_param, char* data);
23int8_t getFruData(std::string& serial, std::string& name);
Vijay Khemkae7d23d02019-03-08 13:13:40 -080024
Vijay Khemka427b2762019-12-12 12:49:25 -080025/* Declare storage functions used here */
26namespace storage
27{
Vijay Khemka63c99be2020-05-27 19:14:35 -070028int getSensorValue(std::string&, double&);
29int getSensorUnit(std::string&, std::string&);
Vijay Khemka58bd5d82019-12-13 11:05:56 -080030} // namespace storage
Vijay Khemka427b2762019-12-12 12:49:25 -080031
Vijay Khemkae7d23d02019-03-08 13:13:40 -080032static int panelNum = (sizeof(panels) / sizeof(struct ctrl_panel)) - 1;
33
34/* Returns the FRU the hand-switch is switched to. If it is switched to BMC
35 * it returns FRU_ALL. Note, if in err, it returns FRU_ALL */
36static uint8_t plat_get_fru_sel()
37{
38 // For Tiogapass it just return 1, can modify to support more platform
39 return 1;
40}
41
42// return 0 on seccuess
43int frame::init(size_t size)
44{
45 // Reset status
46 idx_head = idx_tail = 0;
47 lines = 0;
48 esc_sts = 0;
49 pages = 1;
50
51 if (buf != NULL && max_size == size)
52 {
53 // reinit
54 return 0;
55 }
56
57 if (buf != NULL && max_size != size)
58 {
59 delete[] buf;
60 }
61 // Initialize Configuration
62 title[0] = '\0';
63 buf = new char[size];
64 max_size = size;
65 max_page = size;
66 line_per_page = 7;
67 line_width = 16;
68 overwrite = 0;
69
70 if (buf)
71 return 0;
72 else
73 return -1;
74}
75
76// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -070077int frame::append(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -080078{
79 const size_t buf_size = 64;
80 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -070081 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -080082 int ret;
83
84 ret = parse(lbuf, buf_size, string, indent);
85
86 if (ret < 0)
87 return ret;
88
89 int len = strlen(string);
90 for (ptr = lbuf; *ptr != '\0'; ptr++)
91 {
92 if (isFull())
93 {
94 if (overwrite)
95 {
96 if (buf[idx_head] == LINE_DELIMITER)
97 lines--;
98 idx_head = (idx_head + 1) % max_size;
99 }
100 else
101 return -1;
102 }
103
104 buf[idx_tail] = *ptr;
105 if (*ptr == LINE_DELIMITER)
106 lines++;
107
108 idx_tail = (idx_tail + 1) % max_size;
109 }
110
111 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
112
113 if (pages > max_page)
114 pages = max_page;
115
116 return 0;
117}
118
119// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700120int frame::insert(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800121{
122 const size_t buf_size = 128;
123 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700124 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800125 int ret;
126 int i;
127
128 ret = parse(lbuf, buf_size, string, indent);
129
130 if (ret < 0)
131 return ret;
132
133 for (i = strlen(lbuf) - 1; i >= 0; i--)
134 {
135 ptr = &lbuf[i];
136 if (isFull())
137 {
138 if (overwrite)
139 {
140 idx_tail = (idx_tail + max_size - 1) % max_size;
141 if (buf[idx_tail] == LINE_DELIMITER)
142 lines--;
143 }
144 else
145 return -1;
146 }
147
148 idx_head = (idx_head + max_size - 1) % max_size;
149
150 buf[idx_head] = *ptr;
151 if (*ptr == LINE_DELIMITER)
152 lines++;
153 }
154
155 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
156
157 if (pages > max_page)
158 pages = max_page;
159
160 return 0;
161}
162
163// return page size
Vijay Khemka63c99be2020-05-27 19:14:35 -0700164int frame::getPage(int page, char* page_buf, size_t page_buf_size)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800165{
166 int ret;
167 uint16_t line = 0;
168 uint16_t idx, len;
169
170 if (buf == NULL)
171 return -1;
172
173 // 1-based page
174 if (page > pages || page < 1)
175 return -1;
176
177 if (page_buf == NULL || page_buf_size < 0)
178 return -1;
179
180 ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages);
181 len = strlen(page_buf);
182 if (ret < 0)
183 return -1;
184
185 line = 0;
186 idx = idx_head;
187 while (line < ((page - 1) * line_per_page) && idx != idx_tail)
188 {
189 if (buf[idx] == LINE_DELIMITER)
190 line++;
191 idx = (idx + 1) % max_size;
192 }
193
194 while (line < ((page)*line_per_page) && idx != idx_tail)
195 {
196 if (buf[idx] == LINE_DELIMITER)
197 {
198 line++;
199 }
200 else
201 {
202 page_buf[len++] = buf[idx];
203 if (len == (page_buf_size - 1))
204 {
205 break;
206 }
207 }
208 idx = (idx + 1) % max_size;
209 }
210
211 return len;
212}
213
214// return 1 for frame buffer full
215int frame::isFull()
216{
217 if (buf == NULL)
218 return -1;
219
220 if ((idx_tail + 1) % max_size == idx_head)
221 return 1;
222 else
223 return 0;
224}
225
226// return 1 for Escape Sequence
227int frame::isEscSeq(char chr)
228{
229 uint8_t curr_sts = esc_sts;
230
231 if (esc_sts == 0 && (chr == 0x1b))
232 esc_sts = 1; // Escape Sequence
233 else if (esc_sts == 1 && (chr == 0x5b))
234 esc_sts = 2; // Control Sequence Introducer(CSI)
235 else if (esc_sts == 1 && (chr != 0x5b))
236 esc_sts = 0;
237 else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e))
238 esc_sts = 0;
239
240 if (curr_sts || esc_sts)
241 return 1;
242 else
243 return 0;
244}
245
246// return 0 on success
Vijay Khemka63c99be2020-05-27 19:14:35 -0700247int frame::parse(char* lbuf, size_t buf_size, const char* input, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800248{
249 uint8_t pos, esc;
250 int i;
251 const char *in, *end;
252
253 if (buf == NULL || input == NULL)
254 return -1;
255
256 if (indent >= line_width || indent < 0)
257 return -1;
258
259 in = input;
260 end = in + strlen(input);
261 pos = 0; // line position
262 esc = 0; // escape state
263 i = 0; // buf index
264 while (in != end)
265 {
266 if (i >= buf_size)
267 break;
268
269 if (pos < indent)
270 {
271 // fill indent
272 lbuf[i++] = ' ';
273 pos++;
274 continue;
275 }
276
277 esc = isEscSeq(*in);
278
279 if (!esc && pos == line_width)
280 {
281 lbuf[i++] = LINE_DELIMITER;
282 pos = 0;
283 continue;
284 }
285
286 if (!esc)
287 pos++;
288
289 // fill input data
290 lbuf[i++] = *(in++);
291 }
292
293 // padding
294 while (pos <= line_width)
295 {
296 if (i >= buf_size)
297 break;
298 if (pos < line_width)
299 lbuf[i++] = ' ';
300 else
301 lbuf[i++] = LINE_DELIMITER;
302 pos++;
303 }
304
305 // full
306 if (i >= buf_size)
307 return -1;
308
309 lbuf[i++] = '\0';
310
311 return 0;
312}
313
Vijay Khemka63c99be2020-05-27 19:14:35 -0700314static int chk_cri_sel_update(uint8_t* cri_sel_up)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800315{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700316 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800317 struct stat file_stat;
318 uint8_t pos = plat_get_fru_sel();
319 static uint8_t pre_pos = 0xff;
320
321 fp = fopen("/mnt/data/cri_sel", "r");
322 if (fp)
323 {
324 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
325 (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos))
326 {
327 *cri_sel_up = 1;
328 }
329 else
330 {
331 *cri_sel_up = 0;
332 }
333 fclose(fp);
334 }
335 else
336 {
337 if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos)
338 {
339 *cri_sel_up = 1;
340 }
341 else
342 {
343 *cri_sel_up = 0;
344 }
345 }
346 pre_pos = pos;
347 return 0;
348}
349
Vijay Khemka63c99be2020-05-27 19:14:35 -0700350int plat_udbg_get_frame_info(uint8_t* num)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800351{
352 *num = 3;
353 return 0;
354}
355
Vijay Khemka63c99be2020-05-27 19:14:35 -0700356int plat_udbg_get_updated_frames(uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800357{
358 uint8_t cri_sel_up = 0;
359 uint8_t info_page_up = 1;
360
361 *count = 0;
362
363 // info page update
364 if (info_page_up == 1)
365 {
366 buffer[*count] = 1;
367 *count += 1;
368 }
369
370 // cri sel update
371 chk_cri_sel_update(&cri_sel_up);
372 if (cri_sel_up == 1)
373 {
374 buffer[*count] = 2;
375 *count += 1;
376 }
377
378 // cri sensor update
379 buffer[*count] = 3;
380 *count += 1;
381
382 return 0;
383}
384
Vijay Khemka63c99be2020-05-27 19:14:35 -0700385int plat_udbg_get_post_desc(uint8_t index, uint8_t* next, uint8_t phase,
386 uint8_t* end, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800387{
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700388 nlohmann::json postObj;
389 std::string postCode;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800390
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700391 /* Get post description data stored in json file */
392 std::ifstream file(JSON_POST_DATA_FILE);
393 if (file)
394 {
395 file >> postObj;
396 file.close();
397 }
398 else
399 {
400 phosphor::logging::log<phosphor::logging::level::ERR>(
401 "Post code description file not found",
402 phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE));
403 return -1;
404 }
405
406 std::string phaseStr = "PhaseAny";
407 if (postObj.find(phaseStr) == postObj.end())
408 {
409 phaseStr = "Phase" + std::to_string(phase);
410 }
411
412 if (postObj.find(phaseStr) == postObj.end())
413 {
414 phosphor::logging::log<phosphor::logging::level::ERR>(
415 "Post code phase not available",
416 phosphor::logging::entry("PHASE=%d", phase));
417 return -1;
418 }
419
420 auto phaseObj = postObj[phaseStr];
421 int phaseSize = phaseObj.size();
422
423 for (int i = 0; i < phaseSize; i++)
424 {
425 postCode = phaseObj[i][0];
426 if (index == stoul(postCode, nullptr, 16))
427 {
428 std::string postDesc = phaseObj[i][1];
429 *length = postDesc.size();
430 memcpy(buffer, postDesc.data(), *length);
431 buffer[*length] = '\0';
432
433 if (phaseSize != i + 1)
434 {
435 postCode = phaseObj[i + 1][0];
436 *next = stoul(postCode, nullptr, 16);
437 *end = 0;
438 }
439 else
440 {
441 if (postObj.size() != phase)
442 {
443 std::string nextPhaseStr =
444 "Phase" + std::to_string(phase + 1);
445 postCode = postObj[nextPhaseStr][0][0];
446 *next = stoul(postCode, nullptr, 16);
447 *end = 0;
448 }
449 else
450 {
451 *next = 0xff;
452 *end = 1;
453 }
454 }
455
456 return 0;
457 }
458 }
459
460 phosphor::logging::log<phosphor::logging::level::ERR>(
461 "Post code description data not available",
462 phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index));
463 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800464}
465
Vijay Khemka63c99be2020-05-27 19:14:35 -0700466int plat_udbg_get_gpio_desc(uint8_t index, uint8_t* next, uint8_t* level,
467 uint8_t* def, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800468{
Vijay Khemka38183d62019-08-28 16:19:33 -0700469 nlohmann::json gpioObj;
470 std::string gpioPin;
471
472 /* Get gpio data stored in json file */
473 std::ifstream file(JSON_GPIO_DATA_FILE);
474 if (file)
475 {
476 file >> gpioObj;
477 file.close();
478 }
479 else
480 {
481 phosphor::logging::log<phosphor::logging::level::ERR>(
482 "GPIO pin description file not found",
483 phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s",
484 JSON_GPIO_DATA_FILE));
485 return -1;
486 }
487
488 if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end())
489 {
490 phosphor::logging::log<phosphor::logging::level::ERR>(
491 "GPIO pin details not available",
492 phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY));
493 return -1;
494 }
495
496 auto obj = gpioObj[DEBUG_GPIO_KEY];
497 int objSize = obj.size();
498
499 for (int i = 0; i < objSize; i++)
500 {
501 if (obj[i].size() != GPIO_ARRAY_SIZE)
502 {
503 phosphor::logging::log<phosphor::logging::level::ERR>(
504 "Size of gpio array is incorrect",
505 phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE));
506 return -1;
507 }
508
509 gpioPin = obj[i][GPIO_PIN_INDEX];
510 if (index == stoul(gpioPin, nullptr, 16))
511 {
512 if (objSize != i + 1)
513 {
514 gpioPin = obj[i + 1][GPIO_PIN_INDEX];
515 *next = stoul(gpioPin, nullptr, 16);
516 }
517 else
518 {
519 *next = 0xff;
520 }
521
522 *level = obj[i][GPIO_LEVEL_INDEX];
523 *def = obj[i][GPIO_DEF_INDEX];
524 std::string gpioDesc = obj[i][GPIO_DESC_INDEX];
525 *length = gpioDesc.size();
526 memcpy(buffer, gpioDesc.data(), *length);
527 buffer[*length] = '\0';
528
529 return 0;
530 }
531 }
532
533 phosphor::logging::log<phosphor::logging::level::ERR>(
534 "GPIO pin description data not available",
535 phosphor::logging::entry("GPIO_PIN=0x%x", index));
536 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800537}
538
Vijay Khemka63c99be2020-05-27 19:14:35 -0700539static int udbg_get_cri_sel(uint8_t frame, uint8_t page, uint8_t* next,
540 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800541{
542 int len;
543 int ret;
544 char line_buff[FRAME_PAGE_BUF_SIZE], *fptr;
Vijay Khemka63c99be2020-05-27 19:14:35 -0700545 const char* ptr;
546 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800547 struct stat file_stat;
548 uint8_t pos = plat_get_fru_sel();
549 static uint8_t pre_pos = FRU_ALL;
550 bool pos_changed = pre_pos != pos;
551
552 pre_pos = pos;
553
554 /* Revisit this */
555 fp = fopen("/mnt/data/cri_sel", "r");
556 if (fp)
557 {
558 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
559 (file_stat.st_mtime != frame_sel.mtime || pos_changed))
560 {
561 // initialize and clear frame
562 frame_sel.init(FRAME_BUFF_SIZE);
563 frame_sel.overwrite = 1;
564 frame_sel.max_page = 20;
565 frame_sel.mtime = file_stat.st_mtime;
566 snprintf(frame_sel.title, 32, "Cri SEL");
567
568 while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp))
569 {
570 // Remove newline
571 line_buff[strlen(line_buff) - 1] = '\0';
572 ptr = line_buff;
573 // Find message
574 ptr = strstr(ptr, "local0.err");
575 if (ptr == NULL)
576 {
577 continue;
578 }
579
580 if ((ptr = strrchr(ptr, ':')) == NULL)
581 {
582 continue;
583 }
584 len = strlen(ptr);
585 if (len > 2)
586 {
587 // to skip log string ": "
588 ptr += 2;
589 }
590 // Write new message
591 frame_sel.insert(ptr, 0);
592 }
593 }
594 fclose(fp);
595 }
596 else
597 {
598 // Title only
599 frame_sel.init(FRAME_BUFF_SIZE);
600 snprintf(frame_sel.title, 32, "Cri SEL");
601 frame_sel.mtime = 0;
602 }
603
604 if (page > frame_sel.pages)
605 {
606 return -1;
607 }
608
Vijay Khemka63c99be2020-05-27 19:14:35 -0700609 ret = frame_sel.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800610 if (ret < 0)
611 {
612 *count = 0;
613 return -1;
614 }
615 *count = (uint8_t)ret;
616
617 if (page < frame_sel.pages)
618 *next = page + 1;
619 else
620 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
621 // last page
622
623 return 0;
624}
625
Vijay Khemka63c99be2020-05-27 19:14:35 -0700626static int udbg_get_cri_sensor(uint8_t frame, uint8_t page, uint8_t* next,
627 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800628{
Vijay Khemka427b2762019-12-12 12:49:25 -0800629 int ret;
630 double fvalue;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800631
632 if (page == 1)
633 {
634 // Only update frame data while getting page 1
635
636 // initialize and clear frame
637 frame_snr.init(FRAME_BUFF_SIZE);
638 snprintf(frame_snr.title, 32, "CriSensor");
Vijay Khemka427b2762019-12-12 12:49:25 -0800639
640 nlohmann::json senObj;
641
642 /* Get critical sensor names stored in json file */
643 std::ifstream file(JSON_SENSOR_NAMES_FILE);
644 if (file)
645 {
646 file >> senObj;
647 file.close();
648 }
649 else
650 {
651 phosphor::logging::log<phosphor::logging::level::ERR>(
652 "Critical Sensor names file not found",
653 phosphor::logging::entry("CRI_SENSOR_NAMES_FILE=%s",
654 JSON_SENSOR_NAMES_FILE));
655 return -1;
656 }
657
658 /* Get sensors values for all critical sensors */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700659 for (auto& j : senObj.items())
Vijay Khemka427b2762019-12-12 12:49:25 -0800660 {
661 std::string senName = j.key();
662 auto val = j.value();
663
664 if (ipmi::storage::getSensorValue(senName, fvalue) == 0)
665 {
666 std::stringstream ss;
Vijay Khemkaf43fad42019-12-26 11:47:58 -0800667 int prec = 0; // Default value
668
669 if (val.find("precision") != val.end())
670 prec = val["precision"];
671
672 ss << std::fixed << std::setprecision(prec) << fvalue;
Vijay Khemka427b2762019-12-12 12:49:25 -0800673
674 std::string senStr;
675 if (val.find("short_name") != val.end())
676 senStr = val["short_name"];
677 else
678 senStr = senName;
679
680 senStr += ss.str();
Vijay Khemka58bd5d82019-12-13 11:05:56 -0800681
682 /* Get unit string for sensor and append in output */
683 std::string unitStr;
684 if (ipmi::storage::getSensorUnit(senName, unitStr) == 0)
685 senStr += unitStr;
686
Vijay Khemka427b2762019-12-12 12:49:25 -0800687 frame_snr.append(senStr.c_str(), 0);
688 }
689 else
690 {
691 phosphor::logging::log<phosphor::logging::level::INFO>(
692 "Critical sensor not found",
693 phosphor::logging::entry("CRI_SENSOR_NAME=%s",
694 senName.c_str()));
695 }
696 }
697
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800698 } // End of update frame
699
700 if (page > frame_snr.pages)
701 {
702 return -1;
703 }
704
Vijay Khemka63c99be2020-05-27 19:14:35 -0700705 ret = frame_snr.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800706 if (ret < 0)
707 {
708 *count = 0;
709 return -1;
710 }
711 *count = (uint8_t)ret;
712
713 if (page < frame_snr.pages)
714 *next = page + 1;
715 else
716 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
717 // last page
718
719 return 0;
720}
721
Vijay Khemka63c99be2020-05-27 19:14:35 -0700722static int getBiosVer(std::string& ver)
Vijay Khemka88884b82019-08-27 15:23:07 -0700723{
724 nlohmann::json appObj;
725
726 std::ifstream file(JSON_APP_DATA_FILE);
727 if (file)
728 {
729 file >> appObj;
730 file.close();
731 if (appObj.find(KEY_SYSFW_VER) != appObj.end())
732 {
733 ver = appObj[KEY_SYSFW_VER].get<std::string>();
734 return 0;
735 }
736 }
737
738 return -1;
739}
740
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530741int sendBicCmd(uint8_t netFn, uint8_t cmd, uint8_t bicAddr,
742 std::vector<uint8_t>& cmdData, std::vector<uint8_t>& respData)
743{
744 static constexpr uint8_t lun = 0;
745
746 auto bus = getSdBus();
747
748 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
749 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
750 "org.openbmc.Ipmb", "sendRequest");
751 method.append(bicAddr, netFn, lun, cmd, cmdData);
752
753 auto reply = bus->call(method);
754 if (reply.is_method_error())
755 {
756 phosphor::logging::log<phosphor::logging::level::ERR>(
757 "Error reading from BIC");
758 return -1;
759 }
760
761 IpmbMethodType resp;
762 reply.read(resp);
763
764 respData =
765 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
766
767 return 0;
768}
769
Vijay Khemka63c99be2020-05-27 19:14:35 -0700770int sendMeCmd(uint8_t netFn, uint8_t cmd, std::vector<uint8_t>& cmdData,
771 std::vector<uint8_t>& respData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -0700772{
773 auto bus = getSdBus();
774
775 if (DEBUG)
776 {
777 std::cout << "ME NetFn:cmd " << (int)netFn << ":" << (int)cmd << "\n";
778 std::cout << "ME req data: ";
779 for (auto d : cmdData)
780 {
781 std::cout << d << " ";
782 }
783 std::cout << "\n";
784 }
785
786 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
787 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
788 "org.openbmc.Ipmb", "sendRequest");
789 method.append(meAddress, netFn, lun, cmd, cmdData);
790
791 auto reply = bus->call(method);
792 if (reply.is_method_error())
793 {
794 phosphor::logging::log<phosphor::logging::level::ERR>(
795 "Error reading from ME");
796 return -1;
797 }
798
799 IpmbMethodType resp;
800 reply.read(resp);
801
802 respData =
803 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
804
805 if (DEBUG)
806 {
807 std::cout << "ME resp data: ";
808 for (auto d : respData)
809 {
810 std::cout << d << " ";
811 }
812 std::cout << "\n";
813 }
814
815 return 0;
816}
817
Vijay Khemka63c99be2020-05-27 19:14:35 -0700818static int getMeStatus(std::string& status)
Vijay Khemka317999d2020-01-02 13:43:42 -0800819{
820 uint8_t cmd = 0x01; // Get Device id command
821 uint8_t netFn = 0x06; // Netfn for APP
822 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
823 std::vector<uint8_t> cmdData;
824
825 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
826 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
827 "org.openbmc.Ipmb", "sendRequest");
828 method.append(meAddress, netFn, lun, cmd, cmdData);
829
830 auto reply = bus->call(method);
831 if (reply.is_method_error())
832 {
833 std::cerr << "Error reading from ME\n";
834 return -1;
835 }
836
837 IpmbMethodType resp;
838 reply.read(resp);
839
840 std::vector<uint8_t> data;
841 data = std::get<5>(resp);
842
843 if (DEBUG)
844 {
845 std::cout << "ME Get ID: ";
846 for (size_t d : data)
847 {
848 std::cout << d << " ";
849 }
850 std::cout << "\n";
851 }
852
853 if (data[2] & 0x80)
854 status = "recovery mode";
855 else
856 status = "operation mode";
857
858 return 0;
859}
860
Vijay Khemka63c99be2020-05-27 19:14:35 -0700861static int udbg_get_info_page(uint8_t frame, uint8_t page, uint8_t* next,
862 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800863{
864 char line_buff[1000], *pres_dev = line_buff;
865 uint8_t pos = plat_get_fru_sel();
Vijay Khemka63c99be2020-05-27 19:14:35 -0700866 const char* delim = "\n";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800867 int ret;
868 std::string serialName = "BOARD_SERIAL_NUMBER";
869 std::string partName = "BOARD_PART_NUMBER";
870 std::string verDel = "VERSION=";
871 std::string verPath = "/etc/os-release";
872
873 if (page == 1)
874 {
875 // Only update frame data while getting page 1
876
877 // initialize and clear frame
878 frame_info.init(FRAME_BUFF_SIZE);
879 snprintf(frame_info.title, 32, "SYS_Info");
880
881 // FRU TBD:
882 std::string data;
883 frame_info.append("SN:", 0);
884 if (getFruData(data, serialName) != 0)
885 {
886 data = "Not Found";
887 }
888 frame_info.append(data.c_str(), 1);
889 frame_info.append("PN:", 0);
890 if (getFruData(data, partName) != 0)
891 {
892 data = "Not Found";
893 }
894 frame_info.append(data.c_str(), 1);
895
896 // LAN
897 getNetworkData(3, line_buff);
898 frame_info.append("BMC_IP:", 0);
899 frame_info.append(line_buff, 1);
900 getNetworkData(59, line_buff);
901 frame_info.append("BMC_IPv6:", 0);
902 frame_info.append(line_buff, 1);
903
904 // BMC ver
905 std::ifstream file(verPath);
906 if (file)
907 {
908 std::string line;
909 while (std::getline(file, line))
910 {
911 if (line.find(verDel) != std::string::npos)
912 {
913 std::string bmcVer = line.substr(verDel.size());
914 frame_info.append("BMC_FW_ver:", 0);
915 frame_info.append(bmcVer.c_str(), 1);
916 break;
917 }
918 }
919 }
920
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800921 // BIOS ver
Vijay Khemka88884b82019-08-27 15:23:07 -0700922 std::string biosVer;
923 if (getBiosVer(biosVer) == 0)
924 {
925 frame_info.append("BIOS_FW_ver:", 0);
926 frame_info.append(biosVer.c_str(), 1);
927 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800928
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800929 // ME status
Vijay Khemka317999d2020-01-02 13:43:42 -0800930 std::string meStatus;
931 if (getMeStatus(meStatus) != 0)
932 {
933 phosphor::logging::log<phosphor::logging::level::WARNING>(
934 "Reading ME status failed");
935 meStatus = "unknown";
936 }
937 frame_info.append("ME_status:", 0);
938 frame_info.append(meStatus.c_str(), 1);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800939
Vijay Khemka317999d2020-01-02 13:43:42 -0800940 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800941 // Board ID
942
943 // Battery - Use Escape sequence
944 frame_info.append("Battery:", 0);
945 frame_info.append(ESC_BAT " ", 1);
946 // frame_info.append(&frame_info, esc_bat, 1);
947
948 // MCU Version - Use Escape sequence
949 frame_info.append("MCUbl_ver:", 0);
950 frame_info.append(ESC_MCU_BL_VER, 1);
951 frame_info.append("MCU_ver:", 0);
952 frame_info.append(ESC_MCU_RUN_VER, 1);
953
954 // TBD:
955 // Sys config present device
956
957 } // End of update frame
958
959 if (page > frame_info.pages)
960 {
961 return -1;
962 }
963
Vijay Khemka63c99be2020-05-27 19:14:35 -0700964 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800965 if (ret < 0)
966 {
967 *count = 0;
968 return -1;
969 }
970 *count = (uint8_t)ret;
971
972 if (page < frame_info.pages)
973 *next = page + 1;
974 else
975 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
976 // last page
977
978 return 0;
979}
980
Vijay Khemka63c99be2020-05-27 19:14:35 -0700981int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
982 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800983{
984 switch (frame)
985 {
986 case 1: // info_page
987 return udbg_get_info_page(frame, page, next, count, buffer);
988 case 2: // critical SEL
989 return udbg_get_cri_sel(frame, page, next, count, buffer);
990 case 3: // critical Sensor
991 return udbg_get_cri_sensor(frame, page, next, count, buffer);
992 default:
993 return -1;
994 }
995}
996
997static uint8_t panel_main(uint8_t item)
998{
999 // Update item list when select item 0
1000 switch (item)
1001 {
1002 case 1:
1003 return panels[PANEL_BOOT_ORDER].select(0);
1004 case 2:
1005 return panels[PANEL_POWER_POLICY].select(0);
1006 default:
1007 return PANEL_MAIN;
1008 }
1009}
1010
1011static uint8_t panel_boot_order(uint8_t item)
1012{
1013 int i;
1014 unsigned char buff[MAX_VALUE_LEN], pickup, len;
1015 uint8_t pos = plat_get_fru_sel();
1016
1017 /* To be implemented */
1018 /*
1019 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
1020 {
1021 if (item > 0 && item < SIZE_BOOT_ORDER)
1022 {
1023 pickup = buff[item];
1024 while (item > 1)
1025 {
1026 buff[item] = buff[item -1];
1027 item--;
1028 }
1029 buff[item] = pickup;
1030 buff[0] |= 0x80;
1031 pal_set_boot_order(pos, buff, buff, &len);
1032
1033 // refresh items
1034 return panels[PANEL_BOOT_ORDER].select(0);
1035 }
1036
1037 // '*': boot flags valid, BIOS has not yet read
1038 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32,
1039 "Boot Order%c", (buff[0] & 0x80)?'*':'\0');
1040
1041 for (i = 1; i < SIZE_BOOT_ORDER; i++)
1042 {
1043 switch (buff[i])
1044 {
1045 case 0x0:
1046 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1047 " USB device");
1048 break;
1049 case 0x1:
1050 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1051 " Network v4");
1052 break;
1053 case (0x1 | 0x8):
1054 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1055 " Network v6");
1056 break;
1057 case 0x2:
1058 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1059 " SATA HDD");
1060 break;
1061 case 0x3:
1062 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1063 " SATA-CDROM");
1064 break;
1065 case 0x4:
1066 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1067 " Other");
1068 break;
1069 default:
1070 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
1071 break;
1072 }
1073 }
1074
1075 // remove empty items
1076 for (i--; (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0); i--)
1077 ;
1078
1079 panels[PANEL_BOOT_ORDER].item_num = i;
1080 } else
1081 {
1082 panels[PANEL_BOOT_ORDER].item_num = 0;
1083 }
1084 */
1085 return PANEL_BOOT_ORDER;
1086}
1087
1088static uint8_t panel_power_policy(uint8_t item)
1089{
1090 uint8_t buff[32] = {0};
1091 uint8_t res_len;
1092 uint8_t pos = plat_get_fru_sel();
1093 uint8_t policy;
1094 // uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1095 // POWER_CFG_OFF};
1096
1097 /* To be cleaned */
1098 /*
1099 if (pos != FRU_ALL) {
1100 if (item > 0 && item <= sizeof(pwr_policy_item_map)) {
1101 policy = pwr_policy_item_map[item - 1];
1102 pal_set_power_restore_policy(pos, &policy, NULL);
1103 }
1104 pal_get_chassis_status(pos, NULL, buff, &res_len);
1105 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1106 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32,
1107 "%cPower On", policy == POWER_CFG_ON ? '*' : ' ');
1108 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32,
1109 "%cLast State", policy == POWER_CFG_LPS ? '*' : ' ');
1110 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32,
1111 "%cPower Off", policy == POWER_CFG_OFF ? '*' : ' ');
1112 panels[PANEL_POWER_POLICY].item_num = 3;
1113 } else {
1114 panels[PANEL_POWER_POLICY].item_num = 0;
1115 }
1116 */
1117 return PANEL_POWER_POLICY;
1118}
1119
1120int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001121 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001122{
1123 if (panel > panelNum || panel < PANEL_MAIN)
1124 return IPMI_CC_PARM_OUT_OF_RANGE;
1125
1126 // No more item; End of item list
1127 if (item > panels[panel].item_num)
1128 return IPMI_CC_PARM_OUT_OF_RANGE;
1129
1130 switch (operation)
1131 {
1132 case 0: // Get Description
1133 break;
1134 case 1: // Select item
1135 panel = panels[panel].select(item);
1136 item = 0;
1137 break;
1138 case 2: // Back
1139 panel = panels[panel].parent;
1140 item = 0;
1141 break;
1142 default:
1143 return IPMI_CC_PARM_OUT_OF_RANGE;
1144 }
1145
1146 buffer[0] = panel;
1147 buffer[1] = item;
1148 buffer[2] = strlen(panels[panel].item_str[item]);
1149 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1150 {
1151 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1152 }
1153 *count = buffer[2] + 3;
1154 return IPMI_CC_OK;
1155}
1156
1157} // end of namespace ipmi