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