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