blob: 6e3847f1d52726a89a71fddc2f19f32000de2d27 [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
17#include <host-ipmid/ipmid-api.h>
Vijay Khemkacc0d6d92019-08-27 14:51:17 -070018#include <nlohmann/json.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080019#include <stdbool.h>
20#include <stdio.h>
21#include <sys/stat.h>
22
23#include <fstream>
24#include <iostream>
Vijay Khemkacc0d6d92019-08-27 14:51:17 -070025#include <phosphor-logging/log.hpp>
Vijay Khemka88884b82019-08-27 15:23:07 -070026#include <appcommands.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080027
28namespace ipmi
29{
30
Vijay Khemka11b33a02019-12-13 12:04:20 -080031#define JSON_POST_DATA_FILE "/usr/share/lcd-debug/post_desc.json"
32#define JSON_GPIO_DATA_FILE "/usr/share/lcd-debug/gpio_desc.json"
33
Vijay Khemkae7d23d02019-03-08 13:13:40 -080034#define ETH_INTF_NAME "eth0"
35
36#define ESCAPE "\x1B"
37#define ESC_BAT ESCAPE "B"
38#define ESC_MCU_BL_VER ESCAPE "U"
39#define ESC_MCU_RUN_VER ESCAPE "R"
40#define ESC_ALT ESCAPE "[5;7m"
41#define ESC_RST ESCAPE "[m"
42
43#define LINE_DELIMITER '\x1F'
44
45#define FRAME_BUFF_SIZE 4096
46#define FRAME_PAGE_BUF_SIZE 256
47#define FRU_ALL 0
48#define MAX_VALUE_LEN 64
49
Vijay Khemka38183d62019-08-28 16:19:33 -070050#define DEBUG_GPIO_KEY "GpioDesc"
51#define GPIO_ARRAY_SIZE 4
52#define GPIO_PIN_INDEX 0
53#define GPIO_LEVEL_INDEX 1
54#define GPIO_DEF_INDEX 2
55#define GPIO_DESC_INDEX 3
56
Vijay Khemkae7d23d02019-03-08 13:13:40 -080057/* Used for systems which do not specifically have a
58 * phase, and we want to ignore the phase provided by the
59 * debug card */
60#define PHASE_ANY 0xff
61
62ipmi_ret_t getNetworkData(uint8_t lan_param, char *data);
63int8_t getFruData(std::string &serial, std::string &name);
64
Vijay Khemkae7d23d02019-03-08 13:13:40 -080065typedef struct _sensor_desc
66{
67 char name[16];
68 uint8_t sensor_num;
69 char unit[5];
70 uint8_t fru;
71 uint8_t disp_prec;
72} sensor_desc_t;
73
74struct frame
75{
76 char title[32];
77 size_t max_size;
78 size_t max_page;
79 char *buf;
80 uint16_t idx_head, idx_tail;
81 uint8_t line_per_page;
82 uint8_t line_width;
83 uint16_t lines, pages;
84 uint8_t esc_sts;
85 uint8_t overwrite;
86 time_t mtime;
87 frame() : buf(NULL), pages(0), mtime(0)
88 {
89 }
90 int init(size_t size);
91 int append(const char *string, int indent);
92 int insert(const char *string, int indent);
93 int getPage(int page, char *page_buf, size_t page_buf_size);
94 int isFull();
95 int isEscSeq(char chr);
96 int parse(char *buf, size_t buf_size, const char *input, int indent);
97};
98
99struct frame frame_info;
100struct frame frame_sel;
101struct frame frame_snr;
102
103enum ENUM_PANEL
104{
105 PANEL_MAIN = 1,
106 PANEL_BOOT_ORDER = 2,
107 PANEL_POWER_POLICY = 3,
108};
109
110struct ctrl_panel
111{
112 uint8_t parent;
113 uint8_t item_num;
114 char item_str[8][32];
115 uint8_t (*select)(uint8_t item);
116};
117
118static uint8_t panel_main(uint8_t item);
119static uint8_t panel_boot_order(uint8_t item);
120static uint8_t panel_power_policy(uint8_t item);
121
122static struct ctrl_panel panels[] = {
123 {/* dummy entry for making other to 1-based */},
124 {
125 .parent = PANEL_MAIN,
126 .item_num = 2,
127 .item_str =
128 {
129 "User Setting",
130 ">Boot Order",
131 ">Power Policy",
132 },
133 .select = panel_main,
134 },
135 {
136 .parent = PANEL_MAIN,
137 .item_num = 0,
138 .item_str =
139 {
140 "Boot Order",
141 },
142 .select = panel_boot_order,
143 },
144 {
145 .parent = PANEL_MAIN,
146 .item_num = 0,
147 .item_str =
148 {
149 "Power Policy",
150 },
151 .select = panel_power_policy,
152 },
153};
154
155static int panelNum = (sizeof(panels) / sizeof(struct ctrl_panel)) - 1;
156
157/* Returns the FRU the hand-switch is switched to. If it is switched to BMC
158 * it returns FRU_ALL. Note, if in err, it returns FRU_ALL */
159static uint8_t plat_get_fru_sel()
160{
161 // For Tiogapass it just return 1, can modify to support more platform
162 return 1;
163}
164
165// return 0 on seccuess
166int frame::init(size_t size)
167{
168 // Reset status
169 idx_head = idx_tail = 0;
170 lines = 0;
171 esc_sts = 0;
172 pages = 1;
173
174 if (buf != NULL && max_size == size)
175 {
176 // reinit
177 return 0;
178 }
179
180 if (buf != NULL && max_size != size)
181 {
182 delete[] buf;
183 }
184 // Initialize Configuration
185 title[0] = '\0';
186 buf = new char[size];
187 max_size = size;
188 max_page = size;
189 line_per_page = 7;
190 line_width = 16;
191 overwrite = 0;
192
193 if (buf)
194 return 0;
195 else
196 return -1;
197}
198
199// return 0 on seccuess
200int frame::append(const char *string, int indent)
201{
202 const size_t buf_size = 64;
203 char lbuf[buf_size];
204 char *ptr;
205 int ret;
206
207 ret = parse(lbuf, buf_size, string, indent);
208
209 if (ret < 0)
210 return ret;
211
212 int len = strlen(string);
213 for (ptr = lbuf; *ptr != '\0'; ptr++)
214 {
215 if (isFull())
216 {
217 if (overwrite)
218 {
219 if (buf[idx_head] == LINE_DELIMITER)
220 lines--;
221 idx_head = (idx_head + 1) % max_size;
222 }
223 else
224 return -1;
225 }
226
227 buf[idx_tail] = *ptr;
228 if (*ptr == LINE_DELIMITER)
229 lines++;
230
231 idx_tail = (idx_tail + 1) % max_size;
232 }
233
234 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
235
236 if (pages > max_page)
237 pages = max_page;
238
239 return 0;
240}
241
242// return 0 on seccuess
243int frame::insert(const char *string, int indent)
244{
245 const size_t buf_size = 128;
246 char lbuf[buf_size];
247 char *ptr;
248 int ret;
249 int i;
250
251 ret = parse(lbuf, buf_size, string, indent);
252
253 if (ret < 0)
254 return ret;
255
256 for (i = strlen(lbuf) - 1; i >= 0; i--)
257 {
258 ptr = &lbuf[i];
259 if (isFull())
260 {
261 if (overwrite)
262 {
263 idx_tail = (idx_tail + max_size - 1) % max_size;
264 if (buf[idx_tail] == LINE_DELIMITER)
265 lines--;
266 }
267 else
268 return -1;
269 }
270
271 idx_head = (idx_head + max_size - 1) % max_size;
272
273 buf[idx_head] = *ptr;
274 if (*ptr == LINE_DELIMITER)
275 lines++;
276 }
277
278 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
279
280 if (pages > max_page)
281 pages = max_page;
282
283 return 0;
284}
285
286// return page size
287int frame::getPage(int page, char *page_buf, size_t page_buf_size)
288{
289 int ret;
290 uint16_t line = 0;
291 uint16_t idx, len;
292
293 if (buf == NULL)
294 return -1;
295
296 // 1-based page
297 if (page > pages || page < 1)
298 return -1;
299
300 if (page_buf == NULL || page_buf_size < 0)
301 return -1;
302
303 ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages);
304 len = strlen(page_buf);
305 if (ret < 0)
306 return -1;
307
308 line = 0;
309 idx = idx_head;
310 while (line < ((page - 1) * line_per_page) && idx != idx_tail)
311 {
312 if (buf[idx] == LINE_DELIMITER)
313 line++;
314 idx = (idx + 1) % max_size;
315 }
316
317 while (line < ((page)*line_per_page) && idx != idx_tail)
318 {
319 if (buf[idx] == LINE_DELIMITER)
320 {
321 line++;
322 }
323 else
324 {
325 page_buf[len++] = buf[idx];
326 if (len == (page_buf_size - 1))
327 {
328 break;
329 }
330 }
331 idx = (idx + 1) % max_size;
332 }
333
334 return len;
335}
336
337// return 1 for frame buffer full
338int frame::isFull()
339{
340 if (buf == NULL)
341 return -1;
342
343 if ((idx_tail + 1) % max_size == idx_head)
344 return 1;
345 else
346 return 0;
347}
348
349// return 1 for Escape Sequence
350int frame::isEscSeq(char chr)
351{
352 uint8_t curr_sts = esc_sts;
353
354 if (esc_sts == 0 && (chr == 0x1b))
355 esc_sts = 1; // Escape Sequence
356 else if (esc_sts == 1 && (chr == 0x5b))
357 esc_sts = 2; // Control Sequence Introducer(CSI)
358 else if (esc_sts == 1 && (chr != 0x5b))
359 esc_sts = 0;
360 else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e))
361 esc_sts = 0;
362
363 if (curr_sts || esc_sts)
364 return 1;
365 else
366 return 0;
367}
368
369// return 0 on success
370int frame::parse(char *lbuf, size_t buf_size, const char *input, int indent)
371{
372 uint8_t pos, esc;
373 int i;
374 const char *in, *end;
375
376 if (buf == NULL || input == NULL)
377 return -1;
378
379 if (indent >= line_width || indent < 0)
380 return -1;
381
382 in = input;
383 end = in + strlen(input);
384 pos = 0; // line position
385 esc = 0; // escape state
386 i = 0; // buf index
387 while (in != end)
388 {
389 if (i >= buf_size)
390 break;
391
392 if (pos < indent)
393 {
394 // fill indent
395 lbuf[i++] = ' ';
396 pos++;
397 continue;
398 }
399
400 esc = isEscSeq(*in);
401
402 if (!esc && pos == line_width)
403 {
404 lbuf[i++] = LINE_DELIMITER;
405 pos = 0;
406 continue;
407 }
408
409 if (!esc)
410 pos++;
411
412 // fill input data
413 lbuf[i++] = *(in++);
414 }
415
416 // padding
417 while (pos <= line_width)
418 {
419 if (i >= buf_size)
420 break;
421 if (pos < line_width)
422 lbuf[i++] = ' ';
423 else
424 lbuf[i++] = LINE_DELIMITER;
425 pos++;
426 }
427
428 // full
429 if (i >= buf_size)
430 return -1;
431
432 lbuf[i++] = '\0';
433
434 return 0;
435}
436
437static int chk_cri_sel_update(uint8_t *cri_sel_up)
438{
439 FILE *fp;
440 struct stat file_stat;
441 uint8_t pos = plat_get_fru_sel();
442 static uint8_t pre_pos = 0xff;
443
444 fp = fopen("/mnt/data/cri_sel", "r");
445 if (fp)
446 {
447 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
448 (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos))
449 {
450 *cri_sel_up = 1;
451 }
452 else
453 {
454 *cri_sel_up = 0;
455 }
456 fclose(fp);
457 }
458 else
459 {
460 if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos)
461 {
462 *cri_sel_up = 1;
463 }
464 else
465 {
466 *cri_sel_up = 0;
467 }
468 }
469 pre_pos = pos;
470 return 0;
471}
472
473int plat_udbg_get_frame_info(uint8_t *num)
474{
475 *num = 3;
476 return 0;
477}
478
479int plat_udbg_get_updated_frames(uint8_t *count, uint8_t *buffer)
480{
481 uint8_t cri_sel_up = 0;
482 uint8_t info_page_up = 1;
483
484 *count = 0;
485
486 // info page update
487 if (info_page_up == 1)
488 {
489 buffer[*count] = 1;
490 *count += 1;
491 }
492
493 // cri sel update
494 chk_cri_sel_update(&cri_sel_up);
495 if (cri_sel_up == 1)
496 {
497 buffer[*count] = 2;
498 *count += 1;
499 }
500
501 // cri sensor update
502 buffer[*count] = 3;
503 *count += 1;
504
505 return 0;
506}
507
508int plat_udbg_get_post_desc(uint8_t index, uint8_t *next, uint8_t phase,
509 uint8_t *end, uint8_t *length, uint8_t *buffer)
510{
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700511 nlohmann::json postObj;
512 std::string postCode;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800513
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700514 /* Get post description data stored in json file */
515 std::ifstream file(JSON_POST_DATA_FILE);
516 if (file)
517 {
518 file >> postObj;
519 file.close();
520 }
521 else
522 {
523 phosphor::logging::log<phosphor::logging::level::ERR>(
524 "Post code description file not found",
525 phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE));
526 return -1;
527 }
528
529 std::string phaseStr = "PhaseAny";
530 if (postObj.find(phaseStr) == postObj.end())
531 {
532 phaseStr = "Phase" + std::to_string(phase);
533 }
534
535 if (postObj.find(phaseStr) == postObj.end())
536 {
537 phosphor::logging::log<phosphor::logging::level::ERR>(
538 "Post code phase not available",
539 phosphor::logging::entry("PHASE=%d", phase));
540 return -1;
541 }
542
543 auto phaseObj = postObj[phaseStr];
544 int phaseSize = phaseObj.size();
545
546 for (int i = 0; i < phaseSize; i++)
547 {
548 postCode = phaseObj[i][0];
549 if (index == stoul(postCode, nullptr, 16))
550 {
551 std::string postDesc = phaseObj[i][1];
552 *length = postDesc.size();
553 memcpy(buffer, postDesc.data(), *length);
554 buffer[*length] = '\0';
555
556 if (phaseSize != i + 1)
557 {
558 postCode = phaseObj[i + 1][0];
559 *next = stoul(postCode, nullptr, 16);
560 *end = 0;
561 }
562 else
563 {
564 if (postObj.size() != phase)
565 {
566 std::string nextPhaseStr =
567 "Phase" + std::to_string(phase + 1);
568 postCode = postObj[nextPhaseStr][0][0];
569 *next = stoul(postCode, nullptr, 16);
570 *end = 0;
571 }
572 else
573 {
574 *next = 0xff;
575 *end = 1;
576 }
577 }
578
579 return 0;
580 }
581 }
582
583 phosphor::logging::log<phosphor::logging::level::ERR>(
584 "Post code description data not available",
585 phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index));
586 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800587}
588
589/* Need to implement this */
590int plat_udbg_get_gpio_desc(uint8_t index, uint8_t *next, uint8_t *level,
Vijay Khemka38183d62019-08-28 16:19:33 -0700591 uint8_t *def, uint8_t *length, uint8_t *buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800592{
Vijay Khemka38183d62019-08-28 16:19:33 -0700593 nlohmann::json gpioObj;
594 std::string gpioPin;
595
596 /* Get gpio data stored in json file */
597 std::ifstream file(JSON_GPIO_DATA_FILE);
598 if (file)
599 {
600 file >> gpioObj;
601 file.close();
602 }
603 else
604 {
605 phosphor::logging::log<phosphor::logging::level::ERR>(
606 "GPIO pin description file not found",
607 phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s",
608 JSON_GPIO_DATA_FILE));
609 return -1;
610 }
611
612 if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end())
613 {
614 phosphor::logging::log<phosphor::logging::level::ERR>(
615 "GPIO pin details not available",
616 phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY));
617 return -1;
618 }
619
620 auto obj = gpioObj[DEBUG_GPIO_KEY];
621 int objSize = obj.size();
622
623 for (int i = 0; i < objSize; i++)
624 {
625 if (obj[i].size() != GPIO_ARRAY_SIZE)
626 {
627 phosphor::logging::log<phosphor::logging::level::ERR>(
628 "Size of gpio array is incorrect",
629 phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE));
630 return -1;
631 }
632
633 gpioPin = obj[i][GPIO_PIN_INDEX];
634 if (index == stoul(gpioPin, nullptr, 16))
635 {
636 if (objSize != i + 1)
637 {
638 gpioPin = obj[i + 1][GPIO_PIN_INDEX];
639 *next = stoul(gpioPin, nullptr, 16);
640 }
641 else
642 {
643 *next = 0xff;
644 }
645
646 *level = obj[i][GPIO_LEVEL_INDEX];
647 *def = obj[i][GPIO_DEF_INDEX];
648 std::string gpioDesc = obj[i][GPIO_DESC_INDEX];
649 *length = gpioDesc.size();
650 memcpy(buffer, gpioDesc.data(), *length);
651 buffer[*length] = '\0';
652
653 return 0;
654 }
655 }
656
657 phosphor::logging::log<phosphor::logging::level::ERR>(
658 "GPIO pin description data not available",
659 phosphor::logging::entry("GPIO_PIN=0x%x", index));
660 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800661}
662
663static int udbg_get_cri_sel(uint8_t frame, uint8_t page, uint8_t *next,
664 uint8_t *count, uint8_t *buffer)
665{
666 int len;
667 int ret;
668 char line_buff[FRAME_PAGE_BUF_SIZE], *fptr;
669 const char *ptr;
670 FILE *fp;
671 struct stat file_stat;
672 uint8_t pos = plat_get_fru_sel();
673 static uint8_t pre_pos = FRU_ALL;
674 bool pos_changed = pre_pos != pos;
675
676 pre_pos = pos;
677
678 /* Revisit this */
679 fp = fopen("/mnt/data/cri_sel", "r");
680 if (fp)
681 {
682 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
683 (file_stat.st_mtime != frame_sel.mtime || pos_changed))
684 {
685 // initialize and clear frame
686 frame_sel.init(FRAME_BUFF_SIZE);
687 frame_sel.overwrite = 1;
688 frame_sel.max_page = 20;
689 frame_sel.mtime = file_stat.st_mtime;
690 snprintf(frame_sel.title, 32, "Cri SEL");
691
692 while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp))
693 {
694 // Remove newline
695 line_buff[strlen(line_buff) - 1] = '\0';
696 ptr = line_buff;
697 // Find message
698 ptr = strstr(ptr, "local0.err");
699 if (ptr == NULL)
700 {
701 continue;
702 }
703
704 if ((ptr = strrchr(ptr, ':')) == NULL)
705 {
706 continue;
707 }
708 len = strlen(ptr);
709 if (len > 2)
710 {
711 // to skip log string ": "
712 ptr += 2;
713 }
714 // Write new message
715 frame_sel.insert(ptr, 0);
716 }
717 }
718 fclose(fp);
719 }
720 else
721 {
722 // Title only
723 frame_sel.init(FRAME_BUFF_SIZE);
724 snprintf(frame_sel.title, 32, "Cri SEL");
725 frame_sel.mtime = 0;
726 }
727
728 if (page > frame_sel.pages)
729 {
730 return -1;
731 }
732
733 ret = frame_sel.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE);
734 if (ret < 0)
735 {
736 *count = 0;
737 return -1;
738 }
739 *count = (uint8_t)ret;
740
741 if (page < frame_sel.pages)
742 *next = page + 1;
743 else
744 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
745 // last page
746
747 return 0;
748}
749
750static int udbg_get_cri_sensor(uint8_t frame, uint8_t page, uint8_t *next,
751 uint8_t *count, uint8_t *buffer)
752{
753 char str[32], temp_val[16], temp_thresh[8], print_format[32];
754 int i, ret;
755 float fvalue;
756 sensor_desc_t *cri_sensor = NULL;
757 size_t sensor_count = 0;
758 uint8_t pos = plat_get_fru_sel();
759 uint8_t fru;
760
761 if (page == 1)
762 {
763 // Only update frame data while getting page 1
764
765 // initialize and clear frame
766 frame_snr.init(FRAME_BUFF_SIZE);
767 snprintf(frame_snr.title, 32, "CriSensor");
768 frame_snr.append(str, 0);
769 } // End of update frame
770
771 if (page > frame_snr.pages)
772 {
773 return -1;
774 }
775
776 ret = frame_snr.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE);
777 if (ret < 0)
778 {
779 *count = 0;
780 return -1;
781 }
782 *count = (uint8_t)ret;
783
784 if (page < frame_snr.pages)
785 *next = page + 1;
786 else
787 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
788 // last page
789
790 return 0;
791}
792
Vijay Khemka88884b82019-08-27 15:23:07 -0700793static int getBiosVer(std::string &ver)
794{
795 nlohmann::json appObj;
796
797 std::ifstream file(JSON_APP_DATA_FILE);
798 if (file)
799 {
800 file >> appObj;
801 file.close();
802 if (appObj.find(KEY_SYSFW_VER) != appObj.end())
803 {
804 ver = appObj[KEY_SYSFW_VER].get<std::string>();
805 return 0;
806 }
807 }
808
809 return -1;
810}
811
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800812static int udbg_get_info_page(uint8_t frame, uint8_t page, uint8_t *next,
813 uint8_t *count, uint8_t *buffer)
814{
815 char line_buff[1000], *pres_dev = line_buff;
816 uint8_t pos = plat_get_fru_sel();
817 const char *delim = "\n";
818 int ret;
819 std::string serialName = "BOARD_SERIAL_NUMBER";
820 std::string partName = "BOARD_PART_NUMBER";
821 std::string verDel = "VERSION=";
822 std::string verPath = "/etc/os-release";
823
824 if (page == 1)
825 {
826 // Only update frame data while getting page 1
827
828 // initialize and clear frame
829 frame_info.init(FRAME_BUFF_SIZE);
830 snprintf(frame_info.title, 32, "SYS_Info");
831
832 // FRU TBD:
833 std::string data;
834 frame_info.append("SN:", 0);
835 if (getFruData(data, serialName) != 0)
836 {
837 data = "Not Found";
838 }
839 frame_info.append(data.c_str(), 1);
840 frame_info.append("PN:", 0);
841 if (getFruData(data, partName) != 0)
842 {
843 data = "Not Found";
844 }
845 frame_info.append(data.c_str(), 1);
846
847 // LAN
848 getNetworkData(3, line_buff);
849 frame_info.append("BMC_IP:", 0);
850 frame_info.append(line_buff, 1);
851 getNetworkData(59, line_buff);
852 frame_info.append("BMC_IPv6:", 0);
853 frame_info.append(line_buff, 1);
854
855 // BMC ver
856 std::ifstream file(verPath);
857 if (file)
858 {
859 std::string line;
860 while (std::getline(file, line))
861 {
862 if (line.find(verDel) != std::string::npos)
863 {
864 std::string bmcVer = line.substr(verDel.size());
865 frame_info.append("BMC_FW_ver:", 0);
866 frame_info.append(bmcVer.c_str(), 1);
867 break;
868 }
869 }
870 }
871
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800872 // BIOS ver
Vijay Khemka88884b82019-08-27 15:23:07 -0700873 std::string biosVer;
874 if (getBiosVer(biosVer) == 0)
875 {
876 frame_info.append("BIOS_FW_ver:", 0);
877 frame_info.append(biosVer.c_str(), 1);
878 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800879
Vijay Khemka88884b82019-08-27 15:23:07 -0700880 /* TBD: ME status and Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800881 // ME status
882
883 // Board ID
884
885 // Battery - Use Escape sequence
886 frame_info.append("Battery:", 0);
887 frame_info.append(ESC_BAT " ", 1);
888 // frame_info.append(&frame_info, esc_bat, 1);
889
890 // MCU Version - Use Escape sequence
891 frame_info.append("MCUbl_ver:", 0);
892 frame_info.append(ESC_MCU_BL_VER, 1);
893 frame_info.append("MCU_ver:", 0);
894 frame_info.append(ESC_MCU_RUN_VER, 1);
895
896 // TBD:
897 // Sys config present device
898
899 } // End of update frame
900
901 if (page > frame_info.pages)
902 {
903 return -1;
904 }
905
906 ret = frame_info.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE);
907 if (ret < 0)
908 {
909 *count = 0;
910 return -1;
911 }
912 *count = (uint8_t)ret;
913
914 if (page < frame_info.pages)
915 *next = page + 1;
916 else
917 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
918 // last page
919
920 return 0;
921}
922
923int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t *next,
924 uint8_t *count, uint8_t *buffer)
925{
926 switch (frame)
927 {
928 case 1: // info_page
929 return udbg_get_info_page(frame, page, next, count, buffer);
930 case 2: // critical SEL
931 return udbg_get_cri_sel(frame, page, next, count, buffer);
932 case 3: // critical Sensor
933 return udbg_get_cri_sensor(frame, page, next, count, buffer);
934 default:
935 return -1;
936 }
937}
938
939static uint8_t panel_main(uint8_t item)
940{
941 // Update item list when select item 0
942 switch (item)
943 {
944 case 1:
945 return panels[PANEL_BOOT_ORDER].select(0);
946 case 2:
947 return panels[PANEL_POWER_POLICY].select(0);
948 default:
949 return PANEL_MAIN;
950 }
951}
952
953static uint8_t panel_boot_order(uint8_t item)
954{
955 int i;
956 unsigned char buff[MAX_VALUE_LEN], pickup, len;
957 uint8_t pos = plat_get_fru_sel();
958
959 /* To be implemented */
960 /*
961 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
962 {
963 if (item > 0 && item < SIZE_BOOT_ORDER)
964 {
965 pickup = buff[item];
966 while (item > 1)
967 {
968 buff[item] = buff[item -1];
969 item--;
970 }
971 buff[item] = pickup;
972 buff[0] |= 0x80;
973 pal_set_boot_order(pos, buff, buff, &len);
974
975 // refresh items
976 return panels[PANEL_BOOT_ORDER].select(0);
977 }
978
979 // '*': boot flags valid, BIOS has not yet read
980 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32,
981 "Boot Order%c", (buff[0] & 0x80)?'*':'\0');
982
983 for (i = 1; i < SIZE_BOOT_ORDER; i++)
984 {
985 switch (buff[i])
986 {
987 case 0x0:
988 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
989 " USB device");
990 break;
991 case 0x1:
992 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
993 " Network v4");
994 break;
995 case (0x1 | 0x8):
996 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
997 " Network v6");
998 break;
999 case 0x2:
1000 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1001 " SATA HDD");
1002 break;
1003 case 0x3:
1004 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1005 " SATA-CDROM");
1006 break;
1007 case 0x4:
1008 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1009 " Other");
1010 break;
1011 default:
1012 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
1013 break;
1014 }
1015 }
1016
1017 // remove empty items
1018 for (i--; (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0); i--)
1019 ;
1020
1021 panels[PANEL_BOOT_ORDER].item_num = i;
1022 } else
1023 {
1024 panels[PANEL_BOOT_ORDER].item_num = 0;
1025 }
1026 */
1027 return PANEL_BOOT_ORDER;
1028}
1029
1030static uint8_t panel_power_policy(uint8_t item)
1031{
1032 uint8_t buff[32] = {0};
1033 uint8_t res_len;
1034 uint8_t pos = plat_get_fru_sel();
1035 uint8_t policy;
1036 // uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1037 // POWER_CFG_OFF};
1038
1039 /* To be cleaned */
1040 /*
1041 if (pos != FRU_ALL) {
1042 if (item > 0 && item <= sizeof(pwr_policy_item_map)) {
1043 policy = pwr_policy_item_map[item - 1];
1044 pal_set_power_restore_policy(pos, &policy, NULL);
1045 }
1046 pal_get_chassis_status(pos, NULL, buff, &res_len);
1047 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1048 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32,
1049 "%cPower On", policy == POWER_CFG_ON ? '*' : ' ');
1050 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32,
1051 "%cLast State", policy == POWER_CFG_LPS ? '*' : ' ');
1052 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32,
1053 "%cPower Off", policy == POWER_CFG_OFF ? '*' : ' ');
1054 panels[PANEL_POWER_POLICY].item_num = 3;
1055 } else {
1056 panels[PANEL_POWER_POLICY].item_num = 0;
1057 }
1058 */
1059 return PANEL_POWER_POLICY;
1060}
1061
1062int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
1063 uint8_t *count, uint8_t *buffer)
1064{
1065 if (panel > panelNum || panel < PANEL_MAIN)
1066 return IPMI_CC_PARM_OUT_OF_RANGE;
1067
1068 // No more item; End of item list
1069 if (item > panels[panel].item_num)
1070 return IPMI_CC_PARM_OUT_OF_RANGE;
1071
1072 switch (operation)
1073 {
1074 case 0: // Get Description
1075 break;
1076 case 1: // Select item
1077 panel = panels[panel].select(item);
1078 item = 0;
1079 break;
1080 case 2: // Back
1081 panel = panels[panel].parent;
1082 item = 0;
1083 break;
1084 default:
1085 return IPMI_CC_PARM_OUT_OF_RANGE;
1086 }
1087
1088 buffer[0] = panel;
1089 buffer[1] = item;
1090 buffer[2] = strlen(panels[panel].item_str[item]);
1091 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1092 {
1093 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1094 }
1095 *count = buffer[2] + 3;
1096 return IPMI_CC_OK;
1097}
1098
1099} // end of namespace ipmi