blob: 55ba20c55f2a4e1b2bf886e0e4269cdf37ea9430 [file] [log] [blame]
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001/*
2 * Copyright (c) 2018-present Facebook. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Karthikeyan Pasupathi813f2932022-04-06 14:10:48 +053017#include <usb-dbg.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080018
19namespace ipmi
20{
21
Vijay Khemka63c99be2020-05-27 19:14:35 -070022ipmi_ret_t getNetworkData(uint8_t lan_param, char* data);
23int8_t getFruData(std::string& serial, std::string& name);
Vijay Khemkae7d23d02019-03-08 13:13:40 -080024
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053025bool isMultiHostPlatform();
26
27/* Declare Host Selector interface and path */
28namespace selector
29{
30const std::string path = "/xyz/openbmc_project/Chassis/Buttons/HostSelector";
31const std::string interface =
32 "xyz.openbmc_project.Chassis.HostSelector.Selector";
33const std::string propertyName = "Position";
34} // namespace selector
35
Vijay Khemka427b2762019-12-12 12:49:25 -080036/* Declare storage functions used here */
37namespace storage
38{
Vijay Khemka63c99be2020-05-27 19:14:35 -070039int getSensorValue(std::string&, double&);
40int getSensorUnit(std::string&, std::string&);
Vijay Khemka58bd5d82019-12-13 11:05:56 -080041} // namespace storage
Vijay Khemka427b2762019-12-12 12:49:25 -080042
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053043size_t getSelectorPosition()
44{
45 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
46 std::string service =
47 getService(*dbus, ipmi::selector::interface, ipmi::selector::path);
48 Value variant = getDbusProperty(*dbus, service, ipmi::selector::path,
49 ipmi::selector::interface,
50 ipmi::selector::propertyName);
51 size_t result = std::get<size_t>(variant);
52 return result;
53}
54
Vijay Khemkae7d23d02019-03-08 13:13:40 -080055static int panelNum = (sizeof(panels) / sizeof(struct ctrl_panel)) - 1;
56
57/* Returns the FRU the hand-switch is switched to. If it is switched to BMC
58 * it returns FRU_ALL. Note, if in err, it returns FRU_ALL */
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053059static size_t plat_get_fru_sel()
Vijay Khemkae7d23d02019-03-08 13:13:40 -080060{
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053061 size_t position;
62 bool platform = isMultiHostPlatform();
63
64 if (platform == true)
65 {
66 try
67 {
68 size_t hostPosition = getSelectorPosition();
69 position = hostPosition;
70 if (position == BMC_POSITION)
71 {
72 return FRU_ALL;
73 }
74 }
75 catch (...)
76 {
77 std::cout << "Error reading host selector position" << std::endl;
78 }
79 }
80 else
81 {
82 // For Tiogapass it just return 1, can modify to support more platform
83 position = 1;
84 }
85 return position;
Vijay Khemkae7d23d02019-03-08 13:13:40 -080086}
87
88// return 0 on seccuess
89int frame::init(size_t size)
90{
91 // Reset status
92 idx_head = idx_tail = 0;
93 lines = 0;
94 esc_sts = 0;
95 pages = 1;
96
97 if (buf != NULL && max_size == size)
98 {
99 // reinit
100 return 0;
101 }
102
103 if (buf != NULL && max_size != size)
104 {
105 delete[] buf;
106 }
107 // Initialize Configuration
108 title[0] = '\0';
109 buf = new char[size];
110 max_size = size;
111 max_page = size;
112 line_per_page = 7;
113 line_width = 16;
114 overwrite = 0;
115
116 if (buf)
117 return 0;
118 else
119 return -1;
120}
121
122// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700123int frame::append(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800124{
125 const size_t buf_size = 64;
126 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700127 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800128 int ret;
129
130 ret = parse(lbuf, buf_size, string, indent);
131
132 if (ret < 0)
133 return ret;
134
135 int len = strlen(string);
136 for (ptr = lbuf; *ptr != '\0'; ptr++)
137 {
138 if (isFull())
139 {
140 if (overwrite)
141 {
142 if (buf[idx_head] == LINE_DELIMITER)
143 lines--;
144 idx_head = (idx_head + 1) % max_size;
145 }
146 else
147 return -1;
148 }
149
150 buf[idx_tail] = *ptr;
151 if (*ptr == LINE_DELIMITER)
152 lines++;
153
154 idx_tail = (idx_tail + 1) % max_size;
155 }
156
157 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
158
159 if (pages > max_page)
160 pages = max_page;
161
162 return 0;
163}
164
165// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700166int frame::insert(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800167{
168 const size_t buf_size = 128;
169 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700170 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800171 int ret;
172 int i;
173
174 ret = parse(lbuf, buf_size, string, indent);
175
176 if (ret < 0)
177 return ret;
178
179 for (i = strlen(lbuf) - 1; i >= 0; i--)
180 {
181 ptr = &lbuf[i];
182 if (isFull())
183 {
184 if (overwrite)
185 {
186 idx_tail = (idx_tail + max_size - 1) % max_size;
187 if (buf[idx_tail] == LINE_DELIMITER)
188 lines--;
189 }
190 else
191 return -1;
192 }
193
194 idx_head = (idx_head + max_size - 1) % max_size;
195
196 buf[idx_head] = *ptr;
197 if (*ptr == LINE_DELIMITER)
198 lines++;
199 }
200
201 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
202
203 if (pages > max_page)
204 pages = max_page;
205
206 return 0;
207}
208
209// return page size
Vijay Khemka63c99be2020-05-27 19:14:35 -0700210int frame::getPage(int page, char* page_buf, size_t page_buf_size)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800211{
212 int ret;
213 uint16_t line = 0;
214 uint16_t idx, len;
215
216 if (buf == NULL)
217 return -1;
218
219 // 1-based page
220 if (page > pages || page < 1)
221 return -1;
222
223 if (page_buf == NULL || page_buf_size < 0)
224 return -1;
225
226 ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages);
227 len = strlen(page_buf);
228 if (ret < 0)
229 return -1;
230
231 line = 0;
232 idx = idx_head;
233 while (line < ((page - 1) * line_per_page) && idx != idx_tail)
234 {
235 if (buf[idx] == LINE_DELIMITER)
236 line++;
237 idx = (idx + 1) % max_size;
238 }
239
240 while (line < ((page)*line_per_page) && idx != idx_tail)
241 {
242 if (buf[idx] == LINE_DELIMITER)
243 {
244 line++;
245 }
246 else
247 {
248 page_buf[len++] = buf[idx];
249 if (len == (page_buf_size - 1))
250 {
251 break;
252 }
253 }
254 idx = (idx + 1) % max_size;
255 }
256
257 return len;
258}
259
260// return 1 for frame buffer full
261int frame::isFull()
262{
263 if (buf == NULL)
264 return -1;
265
266 if ((idx_tail + 1) % max_size == idx_head)
267 return 1;
268 else
269 return 0;
270}
271
272// return 1 for Escape Sequence
273int frame::isEscSeq(char chr)
274{
275 uint8_t curr_sts = esc_sts;
276
277 if (esc_sts == 0 && (chr == 0x1b))
278 esc_sts = 1; // Escape Sequence
279 else if (esc_sts == 1 && (chr == 0x5b))
280 esc_sts = 2; // Control Sequence Introducer(CSI)
281 else if (esc_sts == 1 && (chr != 0x5b))
282 esc_sts = 0;
283 else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e))
284 esc_sts = 0;
285
286 if (curr_sts || esc_sts)
287 return 1;
288 else
289 return 0;
290}
291
292// return 0 on success
Vijay Khemka63c99be2020-05-27 19:14:35 -0700293int frame::parse(char* lbuf, size_t buf_size, const char* input, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800294{
295 uint8_t pos, esc;
296 int i;
297 const char *in, *end;
298
299 if (buf == NULL || input == NULL)
300 return -1;
301
302 if (indent >= line_width || indent < 0)
303 return -1;
304
305 in = input;
306 end = in + strlen(input);
307 pos = 0; // line position
308 esc = 0; // escape state
309 i = 0; // buf index
310 while (in != end)
311 {
312 if (i >= buf_size)
313 break;
314
315 if (pos < indent)
316 {
317 // fill indent
318 lbuf[i++] = ' ';
319 pos++;
320 continue;
321 }
322
323 esc = isEscSeq(*in);
324
325 if (!esc && pos == line_width)
326 {
327 lbuf[i++] = LINE_DELIMITER;
328 pos = 0;
329 continue;
330 }
331
332 if (!esc)
333 pos++;
334
335 // fill input data
336 lbuf[i++] = *(in++);
337 }
338
339 // padding
340 while (pos <= line_width)
341 {
342 if (i >= buf_size)
343 break;
344 if (pos < line_width)
345 lbuf[i++] = ' ';
346 else
347 lbuf[i++] = LINE_DELIMITER;
348 pos++;
349 }
350
351 // full
352 if (i >= buf_size)
353 return -1;
354
355 lbuf[i++] = '\0';
356
357 return 0;
358}
359
Vijay Khemka63c99be2020-05-27 19:14:35 -0700360static int chk_cri_sel_update(uint8_t* cri_sel_up)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800361{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700362 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800363 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530364 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800365 static uint8_t pre_pos = 0xff;
366
367 fp = fopen("/mnt/data/cri_sel", "r");
368 if (fp)
369 {
370 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
371 (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos))
372 {
373 *cri_sel_up = 1;
374 }
375 else
376 {
377 *cri_sel_up = 0;
378 }
379 fclose(fp);
380 }
381 else
382 {
383 if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos)
384 {
385 *cri_sel_up = 1;
386 }
387 else
388 {
389 *cri_sel_up = 0;
390 }
391 }
392 pre_pos = pos;
393 return 0;
394}
395
Vijay Khemka63c99be2020-05-27 19:14:35 -0700396int plat_udbg_get_frame_info(uint8_t* num)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800397{
398 *num = 3;
399 return 0;
400}
401
Vijay Khemka63c99be2020-05-27 19:14:35 -0700402int plat_udbg_get_updated_frames(uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800403{
404 uint8_t cri_sel_up = 0;
405 uint8_t info_page_up = 1;
406
407 *count = 0;
408
409 // info page update
410 if (info_page_up == 1)
411 {
412 buffer[*count] = 1;
413 *count += 1;
414 }
415
416 // cri sel update
417 chk_cri_sel_update(&cri_sel_up);
418 if (cri_sel_up == 1)
419 {
420 buffer[*count] = 2;
421 *count += 1;
422 }
423
424 // cri sensor update
425 buffer[*count] = 3;
426 *count += 1;
427
428 return 0;
429}
430
Vijay Khemka63c99be2020-05-27 19:14:35 -0700431int plat_udbg_get_post_desc(uint8_t index, uint8_t* next, uint8_t phase,
432 uint8_t* end, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800433{
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700434 nlohmann::json postObj;
435 std::string postCode;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800436
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700437 /* Get post description data stored in json file */
438 std::ifstream file(JSON_POST_DATA_FILE);
439 if (file)
440 {
441 file >> postObj;
442 file.close();
443 }
444 else
445 {
446 phosphor::logging::log<phosphor::logging::level::ERR>(
447 "Post code description file not found",
448 phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE));
449 return -1;
450 }
451
452 std::string phaseStr = "PhaseAny";
453 if (postObj.find(phaseStr) == postObj.end())
454 {
455 phaseStr = "Phase" + std::to_string(phase);
456 }
457
458 if (postObj.find(phaseStr) == postObj.end())
459 {
460 phosphor::logging::log<phosphor::logging::level::ERR>(
461 "Post code phase not available",
462 phosphor::logging::entry("PHASE=%d", phase));
463 return -1;
464 }
465
466 auto phaseObj = postObj[phaseStr];
467 int phaseSize = phaseObj.size();
468
469 for (int i = 0; i < phaseSize; i++)
470 {
471 postCode = phaseObj[i][0];
472 if (index == stoul(postCode, nullptr, 16))
473 {
474 std::string postDesc = phaseObj[i][1];
475 *length = postDesc.size();
476 memcpy(buffer, postDesc.data(), *length);
477 buffer[*length] = '\0';
478
479 if (phaseSize != i + 1)
480 {
481 postCode = phaseObj[i + 1][0];
482 *next = stoul(postCode, nullptr, 16);
483 *end = 0;
484 }
485 else
486 {
487 if (postObj.size() != phase)
488 {
489 std::string nextPhaseStr =
490 "Phase" + std::to_string(phase + 1);
491 postCode = postObj[nextPhaseStr][0][0];
492 *next = stoul(postCode, nullptr, 16);
493 *end = 0;
494 }
495 else
496 {
497 *next = 0xff;
498 *end = 1;
499 }
500 }
501
502 return 0;
503 }
504 }
505
506 phosphor::logging::log<phosphor::logging::level::ERR>(
507 "Post code description data not available",
508 phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index));
509 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800510}
511
Vijay Khemka63c99be2020-05-27 19:14:35 -0700512int plat_udbg_get_gpio_desc(uint8_t index, uint8_t* next, uint8_t* level,
513 uint8_t* def, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800514{
Vijay Khemka38183d62019-08-28 16:19:33 -0700515 nlohmann::json gpioObj;
516 std::string gpioPin;
517
518 /* Get gpio data stored in json file */
519 std::ifstream file(JSON_GPIO_DATA_FILE);
520 if (file)
521 {
522 file >> gpioObj;
523 file.close();
524 }
525 else
526 {
527 phosphor::logging::log<phosphor::logging::level::ERR>(
528 "GPIO pin description file not found",
529 phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s",
530 JSON_GPIO_DATA_FILE));
531 return -1;
532 }
533
534 if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end())
535 {
536 phosphor::logging::log<phosphor::logging::level::ERR>(
537 "GPIO pin details not available",
538 phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY));
539 return -1;
540 }
541
542 auto obj = gpioObj[DEBUG_GPIO_KEY];
543 int objSize = obj.size();
544
545 for (int i = 0; i < objSize; i++)
546 {
547 if (obj[i].size() != GPIO_ARRAY_SIZE)
548 {
549 phosphor::logging::log<phosphor::logging::level::ERR>(
550 "Size of gpio array is incorrect",
551 phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE));
552 return -1;
553 }
554
555 gpioPin = obj[i][GPIO_PIN_INDEX];
556 if (index == stoul(gpioPin, nullptr, 16))
557 {
558 if (objSize != i + 1)
559 {
560 gpioPin = obj[i + 1][GPIO_PIN_INDEX];
561 *next = stoul(gpioPin, nullptr, 16);
562 }
563 else
564 {
565 *next = 0xff;
566 }
567
568 *level = obj[i][GPIO_LEVEL_INDEX];
569 *def = obj[i][GPIO_DEF_INDEX];
570 std::string gpioDesc = obj[i][GPIO_DESC_INDEX];
571 *length = gpioDesc.size();
572 memcpy(buffer, gpioDesc.data(), *length);
573 buffer[*length] = '\0';
574
575 return 0;
576 }
577 }
578
579 phosphor::logging::log<phosphor::logging::level::ERR>(
580 "GPIO pin description data not available",
581 phosphor::logging::entry("GPIO_PIN=0x%x", index));
582 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800583}
584
Vijay Khemka63c99be2020-05-27 19:14:35 -0700585static int udbg_get_cri_sel(uint8_t frame, uint8_t page, uint8_t* next,
586 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800587{
588 int len;
589 int ret;
590 char line_buff[FRAME_PAGE_BUF_SIZE], *fptr;
Vijay Khemka63c99be2020-05-27 19:14:35 -0700591 const char* ptr;
592 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800593 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530594 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800595 static uint8_t pre_pos = FRU_ALL;
596 bool pos_changed = pre_pos != pos;
597
598 pre_pos = pos;
599
600 /* Revisit this */
601 fp = fopen("/mnt/data/cri_sel", "r");
602 if (fp)
603 {
604 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
605 (file_stat.st_mtime != frame_sel.mtime || pos_changed))
606 {
607 // initialize and clear frame
608 frame_sel.init(FRAME_BUFF_SIZE);
609 frame_sel.overwrite = 1;
610 frame_sel.max_page = 20;
611 frame_sel.mtime = file_stat.st_mtime;
612 snprintf(frame_sel.title, 32, "Cri SEL");
613
614 while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp))
615 {
616 // Remove newline
617 line_buff[strlen(line_buff) - 1] = '\0';
618 ptr = line_buff;
619 // Find message
620 ptr = strstr(ptr, "local0.err");
621 if (ptr == NULL)
622 {
623 continue;
624 }
625
626 if ((ptr = strrchr(ptr, ':')) == NULL)
627 {
628 continue;
629 }
630 len = strlen(ptr);
631 if (len > 2)
632 {
633 // to skip log string ": "
634 ptr += 2;
635 }
636 // Write new message
637 frame_sel.insert(ptr, 0);
638 }
639 }
640 fclose(fp);
641 }
642 else
643 {
644 // Title only
645 frame_sel.init(FRAME_BUFF_SIZE);
646 snprintf(frame_sel.title, 32, "Cri SEL");
647 frame_sel.mtime = 0;
648 }
649
650 if (page > frame_sel.pages)
651 {
652 return -1;
653 }
654
Vijay Khemka63c99be2020-05-27 19:14:35 -0700655 ret = frame_sel.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800656 if (ret < 0)
657 {
658 *count = 0;
659 return -1;
660 }
661 *count = (uint8_t)ret;
662
663 if (page < frame_sel.pages)
664 *next = page + 1;
665 else
666 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
667 // last page
668
669 return 0;
670}
671
Vijay Khemka63c99be2020-05-27 19:14:35 -0700672static int udbg_get_cri_sensor(uint8_t frame, uint8_t page, uint8_t* next,
673 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800674{
Vijay Khemka427b2762019-12-12 12:49:25 -0800675 int ret;
676 double fvalue;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530677 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800678
679 if (page == 1)
680 {
681 // Only update frame data while getting page 1
682
683 // initialize and clear frame
684 frame_snr.init(FRAME_BUFF_SIZE);
685 snprintf(frame_snr.title, 32, "CriSensor");
Vijay Khemka427b2762019-12-12 12:49:25 -0800686
687 nlohmann::json senObj;
688
689 /* Get critical sensor names stored in json file */
690 std::ifstream file(JSON_SENSOR_NAMES_FILE);
691 if (file)
692 {
693 file >> senObj;
694 file.close();
695 }
696 else
697 {
698 phosphor::logging::log<phosphor::logging::level::ERR>(
699 "Critical Sensor names file not found",
700 phosphor::logging::entry("CRI_SENSOR_NAMES_FILE=%s",
701 JSON_SENSOR_NAMES_FILE));
702 return -1;
703 }
704
705 /* Get sensors values for all critical sensors */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700706 for (auto& j : senObj.items())
Vijay Khemka427b2762019-12-12 12:49:25 -0800707 {
708 std::string senName = j.key();
709 auto val = j.value();
710
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530711 if (senName[0] == '_')
712 {
713 senName = std::to_string(pos) + senName;
714 }
715
Vijay Khemka427b2762019-12-12 12:49:25 -0800716 if (ipmi::storage::getSensorValue(senName, fvalue) == 0)
717 {
718 std::stringstream ss;
Vijay Khemkaf43fad42019-12-26 11:47:58 -0800719 int prec = 0; // Default value
720
721 if (val.find("precision") != val.end())
722 prec = val["precision"];
723
724 ss << std::fixed << std::setprecision(prec) << fvalue;
Vijay Khemka427b2762019-12-12 12:49:25 -0800725
726 std::string senStr;
727 if (val.find("short_name") != val.end())
728 senStr = val["short_name"];
729 else
730 senStr = senName;
731
732 senStr += ss.str();
Vijay Khemka58bd5d82019-12-13 11:05:56 -0800733
734 /* Get unit string for sensor and append in output */
735 std::string unitStr;
736 if (ipmi::storage::getSensorUnit(senName, unitStr) == 0)
737 senStr += unitStr;
738
Vijay Khemka427b2762019-12-12 12:49:25 -0800739 frame_snr.append(senStr.c_str(), 0);
740 }
741 else
742 {
743 phosphor::logging::log<phosphor::logging::level::INFO>(
744 "Critical sensor not found",
745 phosphor::logging::entry("CRI_SENSOR_NAME=%s",
746 senName.c_str()));
747 }
748 }
749
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800750 } // End of update frame
751
752 if (page > frame_snr.pages)
753 {
754 return -1;
755 }
756
Vijay Khemka63c99be2020-05-27 19:14:35 -0700757 ret = frame_snr.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800758 if (ret < 0)
759 {
760 *count = 0;
761 return -1;
762 }
763 *count = (uint8_t)ret;
764
765 if (page < frame_snr.pages)
766 *next = page + 1;
767 else
768 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
769 // last page
770
771 return 0;
772}
773
Vijay Khemka63c99be2020-05-27 19:14:35 -0700774static int getBiosVer(std::string& ver)
Vijay Khemka88884b82019-08-27 15:23:07 -0700775{
776 nlohmann::json appObj;
777
778 std::ifstream file(JSON_APP_DATA_FILE);
779 if (file)
780 {
781 file >> appObj;
782 file.close();
783 if (appObj.find(KEY_SYSFW_VER) != appObj.end())
784 {
785 ver = appObj[KEY_SYSFW_VER].get<std::string>();
786 return 0;
787 }
788 }
789
790 return -1;
791}
792
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530793int sendBicCmd(uint8_t netFn, uint8_t cmd, uint8_t bicAddr,
794 std::vector<uint8_t>& cmdData, std::vector<uint8_t>& respData)
795{
796 static constexpr uint8_t lun = 0;
797
798 auto bus = getSdBus();
799
800 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
801 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
802 "org.openbmc.Ipmb", "sendRequest");
803 method.append(bicAddr, netFn, lun, cmd, cmdData);
804
805 auto reply = bus->call(method);
806 if (reply.is_method_error())
807 {
808 phosphor::logging::log<phosphor::logging::level::ERR>(
809 "Error reading from BIC");
810 return -1;
811 }
812
813 IpmbMethodType resp;
814 reply.read(resp);
815
816 respData =
817 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
818
819 return 0;
820}
821
Vijay Khemka63c99be2020-05-27 19:14:35 -0700822int sendMeCmd(uint8_t netFn, uint8_t cmd, std::vector<uint8_t>& cmdData,
823 std::vector<uint8_t>& respData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -0700824{
825 auto bus = getSdBus();
826
827 if (DEBUG)
828 {
829 std::cout << "ME NetFn:cmd " << (int)netFn << ":" << (int)cmd << "\n";
830 std::cout << "ME req data: ";
831 for (auto d : cmdData)
832 {
833 std::cout << d << " ";
834 }
835 std::cout << "\n";
836 }
837
838 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
839 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
840 "org.openbmc.Ipmb", "sendRequest");
841 method.append(meAddress, netFn, lun, cmd, cmdData);
842
843 auto reply = bus->call(method);
844 if (reply.is_method_error())
845 {
846 phosphor::logging::log<phosphor::logging::level::ERR>(
847 "Error reading from ME");
848 return -1;
849 }
850
851 IpmbMethodType resp;
852 reply.read(resp);
853
854 respData =
855 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
856
857 if (DEBUG)
858 {
859 std::cout << "ME resp data: ";
860 for (auto d : respData)
861 {
862 std::cout << d << " ";
863 }
864 std::cout << "\n";
865 }
866
867 return 0;
868}
869
Vijay Khemka63c99be2020-05-27 19:14:35 -0700870static int getMeStatus(std::string& status)
Vijay Khemka317999d2020-01-02 13:43:42 -0800871{
872 uint8_t cmd = 0x01; // Get Device id command
873 uint8_t netFn = 0x06; // Netfn for APP
874 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
875 std::vector<uint8_t> cmdData;
876
877 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
878 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
879 "org.openbmc.Ipmb", "sendRequest");
880 method.append(meAddress, netFn, lun, cmd, cmdData);
881
882 auto reply = bus->call(method);
883 if (reply.is_method_error())
884 {
885 std::cerr << "Error reading from ME\n";
886 return -1;
887 }
888
889 IpmbMethodType resp;
890 reply.read(resp);
891
892 std::vector<uint8_t> data;
893 data = std::get<5>(resp);
894
895 if (DEBUG)
896 {
897 std::cout << "ME Get ID: ";
898 for (size_t d : data)
899 {
900 std::cout << d << " ";
901 }
902 std::cout << "\n";
903 }
904
905 if (data[2] & 0x80)
906 status = "recovery mode";
907 else
908 status = "operation mode";
909
910 return 0;
911}
912
Vijay Khemka63c99be2020-05-27 19:14:35 -0700913static int udbg_get_info_page(uint8_t frame, uint8_t page, uint8_t* next,
914 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800915{
916 char line_buff[1000], *pres_dev = line_buff;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530917 size_t pos = plat_get_fru_sel();
Vijay Khemka63c99be2020-05-27 19:14:35 -0700918 const char* delim = "\n";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800919 int ret;
920 std::string serialName = "BOARD_SERIAL_NUMBER";
921 std::string partName = "BOARD_PART_NUMBER";
922 std::string verDel = "VERSION=";
923 std::string verPath = "/etc/os-release";
924
925 if (page == 1)
926 {
927 // Only update frame data while getting page 1
928
929 // initialize and clear frame
930 frame_info.init(FRAME_BUFF_SIZE);
931 snprintf(frame_info.title, 32, "SYS_Info");
932
933 // FRU TBD:
934 std::string data;
935 frame_info.append("SN:", 0);
936 if (getFruData(data, serialName) != 0)
937 {
938 data = "Not Found";
939 }
940 frame_info.append(data.c_str(), 1);
941 frame_info.append("PN:", 0);
942 if (getFruData(data, partName) != 0)
943 {
944 data = "Not Found";
945 }
946 frame_info.append(data.c_str(), 1);
947
948 // LAN
949 getNetworkData(3, line_buff);
950 frame_info.append("BMC_IP:", 0);
951 frame_info.append(line_buff, 1);
952 getNetworkData(59, line_buff);
953 frame_info.append("BMC_IPv6:", 0);
954 frame_info.append(line_buff, 1);
955
956 // BMC ver
957 std::ifstream file(verPath);
958 if (file)
959 {
960 std::string line;
961 while (std::getline(file, line))
962 {
963 if (line.find(verDel) != std::string::npos)
964 {
965 std::string bmcVer = line.substr(verDel.size());
966 frame_info.append("BMC_FW_ver:", 0);
967 frame_info.append(bmcVer.c_str(), 1);
968 break;
969 }
970 }
971 }
972
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800973 // BIOS ver
Vijay Khemka88884b82019-08-27 15:23:07 -0700974 std::string biosVer;
975 if (getBiosVer(biosVer) == 0)
976 {
977 frame_info.append("BIOS_FW_ver:", 0);
978 frame_info.append(biosVer.c_str(), 1);
979 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800980
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800981 // ME status
Vijay Khemka317999d2020-01-02 13:43:42 -0800982 std::string meStatus;
983 if (getMeStatus(meStatus) != 0)
984 {
985 phosphor::logging::log<phosphor::logging::level::WARNING>(
986 "Reading ME status failed");
987 meStatus = "unknown";
988 }
989 frame_info.append("ME_status:", 0);
990 frame_info.append(meStatus.c_str(), 1);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800991
Vijay Khemka317999d2020-01-02 13:43:42 -0800992 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800993 // Board ID
994
995 // Battery - Use Escape sequence
996 frame_info.append("Battery:", 0);
997 frame_info.append(ESC_BAT " ", 1);
998 // frame_info.append(&frame_info, esc_bat, 1);
999
1000 // MCU Version - Use Escape sequence
1001 frame_info.append("MCUbl_ver:", 0);
1002 frame_info.append(ESC_MCU_BL_VER, 1);
1003 frame_info.append("MCU_ver:", 0);
1004 frame_info.append(ESC_MCU_RUN_VER, 1);
1005
1006 // TBD:
1007 // Sys config present device
1008
1009 } // End of update frame
1010
1011 if (page > frame_info.pages)
1012 {
1013 return -1;
1014 }
1015
Vijay Khemka63c99be2020-05-27 19:14:35 -07001016 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001017 if (ret < 0)
1018 {
1019 *count = 0;
1020 return -1;
1021 }
1022 *count = (uint8_t)ret;
1023
1024 if (page < frame_info.pages)
1025 *next = page + 1;
1026 else
1027 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
1028 // last page
1029
1030 return 0;
1031}
1032
Vijay Khemka63c99be2020-05-27 19:14:35 -07001033int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
1034 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001035{
1036 switch (frame)
1037 {
1038 case 1: // info_page
1039 return udbg_get_info_page(frame, page, next, count, buffer);
1040 case 2: // critical SEL
1041 return udbg_get_cri_sel(frame, page, next, count, buffer);
1042 case 3: // critical Sensor
1043 return udbg_get_cri_sensor(frame, page, next, count, buffer);
1044 default:
1045 return -1;
1046 }
1047}
1048
1049static uint8_t panel_main(uint8_t item)
1050{
1051 // Update item list when select item 0
1052 switch (item)
1053 {
1054 case 1:
1055 return panels[PANEL_BOOT_ORDER].select(0);
1056 case 2:
1057 return panels[PANEL_POWER_POLICY].select(0);
1058 default:
1059 return PANEL_MAIN;
1060 }
1061}
1062
1063static uint8_t panel_boot_order(uint8_t item)
1064{
1065 int i;
1066 unsigned char buff[MAX_VALUE_LEN], pickup, len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301067 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001068
1069 /* To be implemented */
1070 /*
1071 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
1072 {
1073 if (item > 0 && item < SIZE_BOOT_ORDER)
1074 {
1075 pickup = buff[item];
1076 while (item > 1)
1077 {
1078 buff[item] = buff[item -1];
1079 item--;
1080 }
1081 buff[item] = pickup;
1082 buff[0] |= 0x80;
1083 pal_set_boot_order(pos, buff, buff, &len);
1084
1085 // refresh items
1086 return panels[PANEL_BOOT_ORDER].select(0);
1087 }
1088
1089 // '*': boot flags valid, BIOS has not yet read
1090 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32,
1091 "Boot Order%c", (buff[0] & 0x80)?'*':'\0');
1092
1093 for (i = 1; i < SIZE_BOOT_ORDER; i++)
1094 {
1095 switch (buff[i])
1096 {
1097 case 0x0:
1098 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1099 " USB device");
1100 break;
1101 case 0x1:
1102 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1103 " Network v4");
1104 break;
1105 case (0x1 | 0x8):
1106 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1107 " Network v6");
1108 break;
1109 case 0x2:
1110 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1111 " SATA HDD");
1112 break;
1113 case 0x3:
1114 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1115 " SATA-CDROM");
1116 break;
1117 case 0x4:
1118 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1119 " Other");
1120 break;
1121 default:
1122 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
1123 break;
1124 }
1125 }
1126
1127 // remove empty items
1128 for (i--; (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0); i--)
1129 ;
1130
1131 panels[PANEL_BOOT_ORDER].item_num = i;
1132 } else
1133 {
1134 panels[PANEL_BOOT_ORDER].item_num = 0;
1135 }
1136 */
1137 return PANEL_BOOT_ORDER;
1138}
1139
1140static uint8_t panel_power_policy(uint8_t item)
1141{
1142 uint8_t buff[32] = {0};
1143 uint8_t res_len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301144 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001145 uint8_t policy;
1146 // uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1147 // POWER_CFG_OFF};
1148
1149 /* To be cleaned */
1150 /*
1151 if (pos != FRU_ALL) {
1152 if (item > 0 && item <= sizeof(pwr_policy_item_map)) {
1153 policy = pwr_policy_item_map[item - 1];
1154 pal_set_power_restore_policy(pos, &policy, NULL);
1155 }
1156 pal_get_chassis_status(pos, NULL, buff, &res_len);
1157 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1158 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32,
1159 "%cPower On", policy == POWER_CFG_ON ? '*' : ' ');
1160 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32,
1161 "%cLast State", policy == POWER_CFG_LPS ? '*' : ' ');
1162 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32,
1163 "%cPower Off", policy == POWER_CFG_OFF ? '*' : ' ');
1164 panels[PANEL_POWER_POLICY].item_num = 3;
1165 } else {
1166 panels[PANEL_POWER_POLICY].item_num = 0;
1167 }
1168 */
1169 return PANEL_POWER_POLICY;
1170}
1171
1172int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001173 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001174{
1175 if (panel > panelNum || panel < PANEL_MAIN)
1176 return IPMI_CC_PARM_OUT_OF_RANGE;
1177
1178 // No more item; End of item list
1179 if (item > panels[panel].item_num)
1180 return IPMI_CC_PARM_OUT_OF_RANGE;
1181
1182 switch (operation)
1183 {
1184 case 0: // Get Description
1185 break;
1186 case 1: // Select item
1187 panel = panels[panel].select(item);
1188 item = 0;
1189 break;
1190 case 2: // Back
1191 panel = panels[panel].parent;
1192 item = 0;
1193 break;
1194 default:
1195 return IPMI_CC_PARM_OUT_OF_RANGE;
1196 }
1197
1198 buffer[0] = panel;
1199 buffer[1] = item;
1200 buffer[2] = strlen(panels[panel].item_str[item]);
1201 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1202 {
1203 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1204 }
1205 *count = buffer[2] + 3;
1206 return IPMI_CC_OK;
1207}
1208
1209} // end of namespace ipmi