blob: d61c9b247d309cd4491534911d0f86c59f259f5b [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 Khemkae7d23d02019-03-08 13:13:40 -080032#define ETH_INTF_NAME "eth0"
33
34#define ESCAPE "\x1B"
35#define ESC_BAT ESCAPE "B"
36#define ESC_MCU_BL_VER ESCAPE "U"
37#define ESC_MCU_RUN_VER ESCAPE "R"
38#define ESC_ALT ESCAPE "[5;7m"
39#define ESC_RST ESCAPE "[m"
40
41#define LINE_DELIMITER '\x1F'
42
43#define FRAME_BUFF_SIZE 4096
44#define FRAME_PAGE_BUF_SIZE 256
45#define FRU_ALL 0
46#define MAX_VALUE_LEN 64
47
48/* Used for systems which do not specifically have a
49 * phase, and we want to ignore the phase provided by the
50 * debug card */
51#define PHASE_ANY 0xff
52
53ipmi_ret_t getNetworkData(uint8_t lan_param, char *data);
54int8_t getFruData(std::string &serial, std::string &name);
55
Vijay Khemkae7d23d02019-03-08 13:13:40 -080056typedef struct _gpio_desc
57{
58 uint8_t pin;
59 uint8_t level;
60 uint8_t def;
61 char desc[32];
62} gpio_desc_t;
63
64typedef 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,
590 uint8_t *def, uint8_t *count, uint8_t *buffer)
591{
592 return 0;
593}
594
595static int udbg_get_cri_sel(uint8_t frame, uint8_t page, uint8_t *next,
596 uint8_t *count, uint8_t *buffer)
597{
598 int len;
599 int ret;
600 char line_buff[FRAME_PAGE_BUF_SIZE], *fptr;
601 const char *ptr;
602 FILE *fp;
603 struct stat file_stat;
604 uint8_t pos = plat_get_fru_sel();
605 static uint8_t pre_pos = FRU_ALL;
606 bool pos_changed = pre_pos != pos;
607
608 pre_pos = pos;
609
610 /* Revisit this */
611 fp = fopen("/mnt/data/cri_sel", "r");
612 if (fp)
613 {
614 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
615 (file_stat.st_mtime != frame_sel.mtime || pos_changed))
616 {
617 // initialize and clear frame
618 frame_sel.init(FRAME_BUFF_SIZE);
619 frame_sel.overwrite = 1;
620 frame_sel.max_page = 20;
621 frame_sel.mtime = file_stat.st_mtime;
622 snprintf(frame_sel.title, 32, "Cri SEL");
623
624 while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp))
625 {
626 // Remove newline
627 line_buff[strlen(line_buff) - 1] = '\0';
628 ptr = line_buff;
629 // Find message
630 ptr = strstr(ptr, "local0.err");
631 if (ptr == NULL)
632 {
633 continue;
634 }
635
636 if ((ptr = strrchr(ptr, ':')) == NULL)
637 {
638 continue;
639 }
640 len = strlen(ptr);
641 if (len > 2)
642 {
643 // to skip log string ": "
644 ptr += 2;
645 }
646 // Write new message
647 frame_sel.insert(ptr, 0);
648 }
649 }
650 fclose(fp);
651 }
652 else
653 {
654 // Title only
655 frame_sel.init(FRAME_BUFF_SIZE);
656 snprintf(frame_sel.title, 32, "Cri SEL");
657 frame_sel.mtime = 0;
658 }
659
660 if (page > frame_sel.pages)
661 {
662 return -1;
663 }
664
665 ret = frame_sel.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE);
666 if (ret < 0)
667 {
668 *count = 0;
669 return -1;
670 }
671 *count = (uint8_t)ret;
672
673 if (page < frame_sel.pages)
674 *next = page + 1;
675 else
676 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
677 // last page
678
679 return 0;
680}
681
682static int udbg_get_cri_sensor(uint8_t frame, uint8_t page, uint8_t *next,
683 uint8_t *count, uint8_t *buffer)
684{
685 char str[32], temp_val[16], temp_thresh[8], print_format[32];
686 int i, ret;
687 float fvalue;
688 sensor_desc_t *cri_sensor = NULL;
689 size_t sensor_count = 0;
690 uint8_t pos = plat_get_fru_sel();
691 uint8_t fru;
692
693 if (page == 1)
694 {
695 // Only update frame data while getting page 1
696
697 // initialize and clear frame
698 frame_snr.init(FRAME_BUFF_SIZE);
699 snprintf(frame_snr.title, 32, "CriSensor");
700 frame_snr.append(str, 0);
701 } // End of update frame
702
703 if (page > frame_snr.pages)
704 {
705 return -1;
706 }
707
708 ret = frame_snr.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE);
709 if (ret < 0)
710 {
711 *count = 0;
712 return -1;
713 }
714 *count = (uint8_t)ret;
715
716 if (page < frame_snr.pages)
717 *next = page + 1;
718 else
719 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
720 // last page
721
722 return 0;
723}
724
Vijay Khemka88884b82019-08-27 15:23:07 -0700725static int getBiosVer(std::string &ver)
726{
727 nlohmann::json appObj;
728
729 std::ifstream file(JSON_APP_DATA_FILE);
730 if (file)
731 {
732 file >> appObj;
733 file.close();
734 if (appObj.find(KEY_SYSFW_VER) != appObj.end())
735 {
736 ver = appObj[KEY_SYSFW_VER].get<std::string>();
737 return 0;
738 }
739 }
740
741 return -1;
742}
743
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800744static int udbg_get_info_page(uint8_t frame, uint8_t page, uint8_t *next,
745 uint8_t *count, uint8_t *buffer)
746{
747 char line_buff[1000], *pres_dev = line_buff;
748 uint8_t pos = plat_get_fru_sel();
749 const char *delim = "\n";
750 int ret;
751 std::string serialName = "BOARD_SERIAL_NUMBER";
752 std::string partName = "BOARD_PART_NUMBER";
753 std::string verDel = "VERSION=";
754 std::string verPath = "/etc/os-release";
755
756 if (page == 1)
757 {
758 // Only update frame data while getting page 1
759
760 // initialize and clear frame
761 frame_info.init(FRAME_BUFF_SIZE);
762 snprintf(frame_info.title, 32, "SYS_Info");
763
764 // FRU TBD:
765 std::string data;
766 frame_info.append("SN:", 0);
767 if (getFruData(data, serialName) != 0)
768 {
769 data = "Not Found";
770 }
771 frame_info.append(data.c_str(), 1);
772 frame_info.append("PN:", 0);
773 if (getFruData(data, partName) != 0)
774 {
775 data = "Not Found";
776 }
777 frame_info.append(data.c_str(), 1);
778
779 // LAN
780 getNetworkData(3, line_buff);
781 frame_info.append("BMC_IP:", 0);
782 frame_info.append(line_buff, 1);
783 getNetworkData(59, line_buff);
784 frame_info.append("BMC_IPv6:", 0);
785 frame_info.append(line_buff, 1);
786
787 // BMC ver
788 std::ifstream file(verPath);
789 if (file)
790 {
791 std::string line;
792 while (std::getline(file, line))
793 {
794 if (line.find(verDel) != std::string::npos)
795 {
796 std::string bmcVer = line.substr(verDel.size());
797 frame_info.append("BMC_FW_ver:", 0);
798 frame_info.append(bmcVer.c_str(), 1);
799 break;
800 }
801 }
802 }
803
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800804 // BIOS ver
Vijay Khemka88884b82019-08-27 15:23:07 -0700805 std::string biosVer;
806 if (getBiosVer(biosVer) == 0)
807 {
808 frame_info.append("BIOS_FW_ver:", 0);
809 frame_info.append(biosVer.c_str(), 1);
810 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800811
Vijay Khemka88884b82019-08-27 15:23:07 -0700812 /* TBD: ME status and Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800813 // ME status
814
815 // Board ID
816
817 // Battery - Use Escape sequence
818 frame_info.append("Battery:", 0);
819 frame_info.append(ESC_BAT " ", 1);
820 // frame_info.append(&frame_info, esc_bat, 1);
821
822 // MCU Version - Use Escape sequence
823 frame_info.append("MCUbl_ver:", 0);
824 frame_info.append(ESC_MCU_BL_VER, 1);
825 frame_info.append("MCU_ver:", 0);
826 frame_info.append(ESC_MCU_RUN_VER, 1);
827
828 // TBD:
829 // Sys config present device
830
831 } // End of update frame
832
833 if (page > frame_info.pages)
834 {
835 return -1;
836 }
837
838 ret = frame_info.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE);
839 if (ret < 0)
840 {
841 *count = 0;
842 return -1;
843 }
844 *count = (uint8_t)ret;
845
846 if (page < frame_info.pages)
847 *next = page + 1;
848 else
849 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
850 // last page
851
852 return 0;
853}
854
855int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t *next,
856 uint8_t *count, uint8_t *buffer)
857{
858 switch (frame)
859 {
860 case 1: // info_page
861 return udbg_get_info_page(frame, page, next, count, buffer);
862 case 2: // critical SEL
863 return udbg_get_cri_sel(frame, page, next, count, buffer);
864 case 3: // critical Sensor
865 return udbg_get_cri_sensor(frame, page, next, count, buffer);
866 default:
867 return -1;
868 }
869}
870
871static uint8_t panel_main(uint8_t item)
872{
873 // Update item list when select item 0
874 switch (item)
875 {
876 case 1:
877 return panels[PANEL_BOOT_ORDER].select(0);
878 case 2:
879 return panels[PANEL_POWER_POLICY].select(0);
880 default:
881 return PANEL_MAIN;
882 }
883}
884
885static uint8_t panel_boot_order(uint8_t item)
886{
887 int i;
888 unsigned char buff[MAX_VALUE_LEN], pickup, len;
889 uint8_t pos = plat_get_fru_sel();
890
891 /* To be implemented */
892 /*
893 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
894 {
895 if (item > 0 && item < SIZE_BOOT_ORDER)
896 {
897 pickup = buff[item];
898 while (item > 1)
899 {
900 buff[item] = buff[item -1];
901 item--;
902 }
903 buff[item] = pickup;
904 buff[0] |= 0x80;
905 pal_set_boot_order(pos, buff, buff, &len);
906
907 // refresh items
908 return panels[PANEL_BOOT_ORDER].select(0);
909 }
910
911 // '*': boot flags valid, BIOS has not yet read
912 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32,
913 "Boot Order%c", (buff[0] & 0x80)?'*':'\0');
914
915 for (i = 1; i < SIZE_BOOT_ORDER; i++)
916 {
917 switch (buff[i])
918 {
919 case 0x0:
920 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
921 " USB device");
922 break;
923 case 0x1:
924 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
925 " Network v4");
926 break;
927 case (0x1 | 0x8):
928 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
929 " Network v6");
930 break;
931 case 0x2:
932 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
933 " SATA HDD");
934 break;
935 case 0x3:
936 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
937 " SATA-CDROM");
938 break;
939 case 0x4:
940 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
941 " Other");
942 break;
943 default:
944 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
945 break;
946 }
947 }
948
949 // remove empty items
950 for (i--; (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0); i--)
951 ;
952
953 panels[PANEL_BOOT_ORDER].item_num = i;
954 } else
955 {
956 panels[PANEL_BOOT_ORDER].item_num = 0;
957 }
958 */
959 return PANEL_BOOT_ORDER;
960}
961
962static uint8_t panel_power_policy(uint8_t item)
963{
964 uint8_t buff[32] = {0};
965 uint8_t res_len;
966 uint8_t pos = plat_get_fru_sel();
967 uint8_t policy;
968 // uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
969 // POWER_CFG_OFF};
970
971 /* To be cleaned */
972 /*
973 if (pos != FRU_ALL) {
974 if (item > 0 && item <= sizeof(pwr_policy_item_map)) {
975 policy = pwr_policy_item_map[item - 1];
976 pal_set_power_restore_policy(pos, &policy, NULL);
977 }
978 pal_get_chassis_status(pos, NULL, buff, &res_len);
979 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
980 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32,
981 "%cPower On", policy == POWER_CFG_ON ? '*' : ' ');
982 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32,
983 "%cLast State", policy == POWER_CFG_LPS ? '*' : ' ');
984 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32,
985 "%cPower Off", policy == POWER_CFG_OFF ? '*' : ' ');
986 panels[PANEL_POWER_POLICY].item_num = 3;
987 } else {
988 panels[PANEL_POWER_POLICY].item_num = 0;
989 }
990 */
991 return PANEL_POWER_POLICY;
992}
993
994int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
995 uint8_t *count, uint8_t *buffer)
996{
997 if (panel > panelNum || panel < PANEL_MAIN)
998 return IPMI_CC_PARM_OUT_OF_RANGE;
999
1000 // No more item; End of item list
1001 if (item > panels[panel].item_num)
1002 return IPMI_CC_PARM_OUT_OF_RANGE;
1003
1004 switch (operation)
1005 {
1006 case 0: // Get Description
1007 break;
1008 case 1: // Select item
1009 panel = panels[panel].select(item);
1010 item = 0;
1011 break;
1012 case 2: // Back
1013 panel = panels[panel].parent;
1014 item = 0;
1015 break;
1016 default:
1017 return IPMI_CC_PARM_OUT_OF_RANGE;
1018 }
1019
1020 buffer[0] = panel;
1021 buffer[1] = item;
1022 buffer[2] = strlen(panels[panel].item_str[item]);
1023 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1024 {
1025 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1026 }
1027 *count = buffer[2] + 3;
1028 return IPMI_CC_OK;
1029}
1030
1031} // end of namespace ipmi