blob: 9a718b7d2e6b5ab4df52f328fdaf71ca3d545fcc [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>
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +053018#include <commandutils.hpp>
Vijay Khemkae7d23d02019-03-08 13:13:40 -080019
20namespace ipmi
21{
22
Vijay Khemka63c99be2020-05-27 19:14:35 -070023ipmi_ret_t getNetworkData(uint8_t lan_param, char* data);
24int8_t getFruData(std::string& serial, std::string& name);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +053025int8_t sysConfig(std::vector<std::string>& data, size_t pos);
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +053026int8_t procInfo(std::string& result, size_t pos);
Vijay Khemkae7d23d02019-03-08 13:13:40 -080027
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053028bool isMultiHostPlatform();
29
30/* Declare Host Selector interface and path */
31namespace selector
32{
33const std::string path = "/xyz/openbmc_project/Chassis/Buttons/HostSelector";
34const std::string interface =
Potin Laicff150e2022-09-19 09:34:57 +080035 "xyz.openbmc_project.Chassis.Buttons.HostSelector";
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053036const std::string propertyName = "Position";
37} // namespace selector
38
Vijay Khemka427b2762019-12-12 12:49:25 -080039/* Declare storage functions used here */
40namespace storage
41{
Vijay Khemka63c99be2020-05-27 19:14:35 -070042int getSensorValue(std::string&, double&);
43int getSensorUnit(std::string&, std::string&);
Vijay Khemka58bd5d82019-12-13 11:05:56 -080044} // namespace storage
Vijay Khemka427b2762019-12-12 12:49:25 -080045
Potin Laif24c78e2022-10-27 17:13:14 +080046size_t getMaxHostPosition()
47{
48 try
49 {
50 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
51 std::string service =
52 getService(*dbus, ipmi::selector::interface, ipmi::selector::path);
53 Value variant =
54 getDbusProperty(*dbus, service, ipmi::selector::path,
55 ipmi::selector::interface, "MaxPosition");
56 size_t result = std::get<size_t>(variant);
57 return result;
58 }
59 catch (...)
60 {
61 phosphor::logging::log<phosphor::logging::level::ERR>(
62 "Failed to get MaxPosition from DBus");
63 }
64
65 return MAX_HOST_POS;
66}
67
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053068size_t getSelectorPosition()
69{
70 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
71 std::string service =
72 getService(*dbus, ipmi::selector::interface, ipmi::selector::path);
73 Value variant = getDbusProperty(*dbus, service, ipmi::selector::path,
74 ipmi::selector::interface,
75 ipmi::selector::propertyName);
76 size_t result = std::get<size_t>(variant);
77 return result;
78}
79
Vijay Khemkae7d23d02019-03-08 13:13:40 -080080static int panelNum = (sizeof(panels) / sizeof(struct ctrl_panel)) - 1;
81
82/* Returns the FRU the hand-switch is switched to. If it is switched to BMC
83 * it returns FRU_ALL. Note, if in err, it returns FRU_ALL */
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053084static size_t plat_get_fru_sel()
Vijay Khemkae7d23d02019-03-08 13:13:40 -080085{
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053086 size_t position;
87 bool platform = isMultiHostPlatform();
88
89 if (platform == true)
90 {
91 try
92 {
93 size_t hostPosition = getSelectorPosition();
94 position = hostPosition;
95 if (position == BMC_POSITION)
96 {
97 return FRU_ALL;
98 }
99 }
100 catch (...)
101 {
102 std::cout << "Error reading host selector position" << std::endl;
103 }
104 }
105 else
106 {
107 // For Tiogapass it just return 1, can modify to support more platform
108 position = 1;
109 }
110 return position;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800111}
112
113// return 0 on seccuess
114int frame::init(size_t size)
115{
116 // Reset status
117 idx_head = idx_tail = 0;
118 lines = 0;
119 esc_sts = 0;
120 pages = 1;
121
122 if (buf != NULL && max_size == size)
123 {
124 // reinit
125 return 0;
126 }
127
128 if (buf != NULL && max_size != size)
129 {
130 delete[] buf;
131 }
132 // Initialize Configuration
133 title[0] = '\0';
134 buf = new char[size];
135 max_size = size;
136 max_page = size;
137 line_per_page = 7;
138 line_width = 16;
139 overwrite = 0;
140
141 if (buf)
142 return 0;
143 else
144 return -1;
145}
146
147// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700148int frame::append(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800149{
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530150 const size_t buf_size = 128;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800151 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700152 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800153 int ret;
154
155 ret = parse(lbuf, buf_size, string, indent);
156
157 if (ret < 0)
158 return ret;
159
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800160 for (ptr = lbuf; *ptr != '\0'; ptr++)
161 {
162 if (isFull())
163 {
164 if (overwrite)
165 {
166 if (buf[idx_head] == LINE_DELIMITER)
167 lines--;
168 idx_head = (idx_head + 1) % max_size;
169 }
170 else
171 return -1;
172 }
173
174 buf[idx_tail] = *ptr;
175 if (*ptr == LINE_DELIMITER)
176 lines++;
177
178 idx_tail = (idx_tail + 1) % max_size;
179 }
180
181 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
182
183 if (pages > max_page)
184 pages = max_page;
185
186 return 0;
187}
188
189// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700190int frame::insert(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800191{
192 const size_t buf_size = 128;
193 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700194 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800195 int ret;
196 int i;
197
198 ret = parse(lbuf, buf_size, string, indent);
199
200 if (ret < 0)
201 return ret;
202
203 for (i = strlen(lbuf) - 1; i >= 0; i--)
204 {
205 ptr = &lbuf[i];
206 if (isFull())
207 {
208 if (overwrite)
209 {
210 idx_tail = (idx_tail + max_size - 1) % max_size;
211 if (buf[idx_tail] == LINE_DELIMITER)
212 lines--;
213 }
214 else
215 return -1;
216 }
217
218 idx_head = (idx_head + max_size - 1) % max_size;
219
220 buf[idx_head] = *ptr;
221 if (*ptr == LINE_DELIMITER)
222 lines++;
223 }
224
225 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
226
227 if (pages > max_page)
228 pages = max_page;
229
230 return 0;
231}
232
233// return page size
Vijay Khemka63c99be2020-05-27 19:14:35 -0700234int frame::getPage(int page, char* page_buf, size_t page_buf_size)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800235{
236 int ret;
237 uint16_t line = 0;
238 uint16_t idx, len;
239
240 if (buf == NULL)
241 return -1;
242
243 // 1-based page
244 if (page > pages || page < 1)
245 return -1;
246
Willy Tue39f9392022-06-15 13:24:20 -0700247 if (page_buf == NULL || page_buf_size == 0)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800248 return -1;
249
250 ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages);
251 len = strlen(page_buf);
252 if (ret < 0)
253 return -1;
254
255 line = 0;
256 idx = idx_head;
257 while (line < ((page - 1) * line_per_page) && idx != idx_tail)
258 {
259 if (buf[idx] == LINE_DELIMITER)
260 line++;
261 idx = (idx + 1) % max_size;
262 }
263
264 while (line < ((page)*line_per_page) && idx != idx_tail)
265 {
266 if (buf[idx] == LINE_DELIMITER)
267 {
268 line++;
269 }
270 else
271 {
272 page_buf[len++] = buf[idx];
273 if (len == (page_buf_size - 1))
274 {
275 break;
276 }
277 }
278 idx = (idx + 1) % max_size;
279 }
280
281 return len;
282}
283
284// return 1 for frame buffer full
285int frame::isFull()
286{
287 if (buf == NULL)
288 return -1;
289
290 if ((idx_tail + 1) % max_size == idx_head)
291 return 1;
292 else
293 return 0;
294}
295
296// return 1 for Escape Sequence
297int frame::isEscSeq(char chr)
298{
299 uint8_t curr_sts = esc_sts;
300
301 if (esc_sts == 0 && (chr == 0x1b))
302 esc_sts = 1; // Escape Sequence
303 else if (esc_sts == 1 && (chr == 0x5b))
304 esc_sts = 2; // Control Sequence Introducer(CSI)
305 else if (esc_sts == 1 && (chr != 0x5b))
306 esc_sts = 0;
307 else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e))
308 esc_sts = 0;
309
310 if (curr_sts || esc_sts)
311 return 1;
312 else
313 return 0;
314}
315
316// return 0 on success
Vijay Khemka63c99be2020-05-27 19:14:35 -0700317int frame::parse(char* lbuf, size_t buf_size, const char* input, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800318{
319 uint8_t pos, esc;
Willy Tue39f9392022-06-15 13:24:20 -0700320 size_t i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800321 const char *in, *end;
322
323 if (buf == NULL || input == NULL)
324 return -1;
325
326 if (indent >= line_width || indent < 0)
327 return -1;
328
329 in = input;
330 end = in + strlen(input);
331 pos = 0; // line position
332 esc = 0; // escape state
333 i = 0; // buf index
334 while (in != end)
335 {
336 if (i >= buf_size)
337 break;
338
339 if (pos < indent)
340 {
341 // fill indent
342 lbuf[i++] = ' ';
343 pos++;
344 continue;
345 }
346
347 esc = isEscSeq(*in);
348
349 if (!esc && pos == line_width)
350 {
351 lbuf[i++] = LINE_DELIMITER;
352 pos = 0;
353 continue;
354 }
355
356 if (!esc)
357 pos++;
358
359 // fill input data
360 lbuf[i++] = *(in++);
361 }
362
363 // padding
364 while (pos <= line_width)
365 {
366 if (i >= buf_size)
367 break;
368 if (pos < line_width)
369 lbuf[i++] = ' ';
370 else
371 lbuf[i++] = LINE_DELIMITER;
372 pos++;
373 }
374
375 // full
376 if (i >= buf_size)
377 return -1;
378
379 lbuf[i++] = '\0';
380
381 return 0;
382}
383
Vijay Khemka63c99be2020-05-27 19:14:35 -0700384static int chk_cri_sel_update(uint8_t* cri_sel_up)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800385{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700386 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800387 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530388 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800389 static uint8_t pre_pos = 0xff;
390
391 fp = fopen("/mnt/data/cri_sel", "r");
392 if (fp)
393 {
394 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
395 (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos))
396 {
397 *cri_sel_up = 1;
398 }
399 else
400 {
401 *cri_sel_up = 0;
402 }
403 fclose(fp);
404 }
405 else
406 {
407 if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos)
408 {
409 *cri_sel_up = 1;
410 }
411 else
412 {
413 *cri_sel_up = 0;
414 }
415 }
416 pre_pos = pos;
417 return 0;
418}
419
Vijay Khemka63c99be2020-05-27 19:14:35 -0700420int plat_udbg_get_frame_info(uint8_t* num)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800421{
422 *num = 3;
423 return 0;
424}
425
Vijay Khemka63c99be2020-05-27 19:14:35 -0700426int plat_udbg_get_updated_frames(uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800427{
428 uint8_t cri_sel_up = 0;
429 uint8_t info_page_up = 1;
430
431 *count = 0;
432
433 // info page update
434 if (info_page_up == 1)
435 {
436 buffer[*count] = 1;
437 *count += 1;
438 }
439
440 // cri sel update
441 chk_cri_sel_update(&cri_sel_up);
442 if (cri_sel_up == 1)
443 {
444 buffer[*count] = 2;
445 *count += 1;
446 }
447
448 // cri sensor update
449 buffer[*count] = 3;
450 *count += 1;
451
452 return 0;
453}
454
Vijay Khemka63c99be2020-05-27 19:14:35 -0700455int plat_udbg_get_post_desc(uint8_t index, uint8_t* next, uint8_t phase,
456 uint8_t* end, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800457{
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700458 nlohmann::json postObj;
459 std::string postCode;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800460
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700461 /* Get post description data stored in json file */
462 std::ifstream file(JSON_POST_DATA_FILE);
463 if (file)
464 {
465 file >> postObj;
466 file.close();
467 }
468 else
469 {
470 phosphor::logging::log<phosphor::logging::level::ERR>(
471 "Post code description file not found",
472 phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE));
473 return -1;
474 }
475
476 std::string phaseStr = "PhaseAny";
477 if (postObj.find(phaseStr) == postObj.end())
478 {
479 phaseStr = "Phase" + std::to_string(phase);
480 }
481
482 if (postObj.find(phaseStr) == postObj.end())
483 {
484 phosphor::logging::log<phosphor::logging::level::ERR>(
485 "Post code phase not available",
486 phosphor::logging::entry("PHASE=%d", phase));
487 return -1;
488 }
489
490 auto phaseObj = postObj[phaseStr];
491 int phaseSize = phaseObj.size();
492
493 for (int i = 0; i < phaseSize; i++)
494 {
495 postCode = phaseObj[i][0];
496 if (index == stoul(postCode, nullptr, 16))
497 {
498 std::string postDesc = phaseObj[i][1];
499 *length = postDesc.size();
500 memcpy(buffer, postDesc.data(), *length);
501 buffer[*length] = '\0';
502
503 if (phaseSize != i + 1)
504 {
505 postCode = phaseObj[i + 1][0];
506 *next = stoul(postCode, nullptr, 16);
507 *end = 0;
508 }
509 else
510 {
511 if (postObj.size() != phase)
512 {
513 std::string nextPhaseStr =
514 "Phase" + std::to_string(phase + 1);
515 postCode = postObj[nextPhaseStr][0][0];
516 *next = stoul(postCode, nullptr, 16);
517 *end = 0;
518 }
519 else
520 {
521 *next = 0xff;
522 *end = 1;
523 }
524 }
525
526 return 0;
527 }
528 }
529
530 phosphor::logging::log<phosphor::logging::level::ERR>(
531 "Post code description data not available",
532 phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index));
533 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800534}
535
Vijay Khemka63c99be2020-05-27 19:14:35 -0700536int plat_udbg_get_gpio_desc(uint8_t index, uint8_t* next, uint8_t* level,
537 uint8_t* def, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800538{
Vijay Khemka38183d62019-08-28 16:19:33 -0700539 nlohmann::json gpioObj;
540 std::string gpioPin;
541
542 /* Get gpio data stored in json file */
543 std::ifstream file(JSON_GPIO_DATA_FILE);
544 if (file)
545 {
546 file >> gpioObj;
547 file.close();
548 }
549 else
550 {
551 phosphor::logging::log<phosphor::logging::level::ERR>(
552 "GPIO pin description file not found",
553 phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s",
554 JSON_GPIO_DATA_FILE));
555 return -1;
556 }
557
558 if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end())
559 {
560 phosphor::logging::log<phosphor::logging::level::ERR>(
561 "GPIO pin details not available",
562 phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY));
563 return -1;
564 }
565
566 auto obj = gpioObj[DEBUG_GPIO_KEY];
567 int objSize = obj.size();
568
569 for (int i = 0; i < objSize; i++)
570 {
571 if (obj[i].size() != GPIO_ARRAY_SIZE)
572 {
573 phosphor::logging::log<phosphor::logging::level::ERR>(
574 "Size of gpio array is incorrect",
575 phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE));
576 return -1;
577 }
578
579 gpioPin = obj[i][GPIO_PIN_INDEX];
580 if (index == stoul(gpioPin, nullptr, 16))
581 {
582 if (objSize != i + 1)
583 {
584 gpioPin = obj[i + 1][GPIO_PIN_INDEX];
585 *next = stoul(gpioPin, nullptr, 16);
586 }
587 else
588 {
589 *next = 0xff;
590 }
591
592 *level = obj[i][GPIO_LEVEL_INDEX];
593 *def = obj[i][GPIO_DEF_INDEX];
594 std::string gpioDesc = obj[i][GPIO_DESC_INDEX];
595 *length = gpioDesc.size();
596 memcpy(buffer, gpioDesc.data(), *length);
597 buffer[*length] = '\0';
598
599 return 0;
600 }
601 }
602
603 phosphor::logging::log<phosphor::logging::level::ERR>(
604 "GPIO pin description data not available",
605 phosphor::logging::entry("GPIO_PIN=0x%x", index));
606 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800607}
608
Willy Tue39f9392022-06-15 13:24:20 -0700609static int udbg_get_cri_sel(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700610 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800611{
612 int len;
613 int ret;
Willy Tue39f9392022-06-15 13:24:20 -0700614 char line_buff[FRAME_PAGE_BUF_SIZE];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700615 const char* ptr;
616 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800617 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530618 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800619 static uint8_t pre_pos = FRU_ALL;
620 bool pos_changed = pre_pos != pos;
621
622 pre_pos = pos;
623
624 /* Revisit this */
625 fp = fopen("/mnt/data/cri_sel", "r");
626 if (fp)
627 {
628 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
629 (file_stat.st_mtime != frame_sel.mtime || pos_changed))
630 {
631 // initialize and clear frame
632 frame_sel.init(FRAME_BUFF_SIZE);
633 frame_sel.overwrite = 1;
634 frame_sel.max_page = 20;
635 frame_sel.mtime = file_stat.st_mtime;
636 snprintf(frame_sel.title, 32, "Cri SEL");
637
638 while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp))
639 {
640 // Remove newline
641 line_buff[strlen(line_buff) - 1] = '\0';
642 ptr = line_buff;
643 // Find message
644 ptr = strstr(ptr, "local0.err");
645 if (ptr == NULL)
646 {
647 continue;
648 }
649
650 if ((ptr = strrchr(ptr, ':')) == NULL)
651 {
652 continue;
653 }
654 len = strlen(ptr);
655 if (len > 2)
656 {
657 // to skip log string ": "
658 ptr += 2;
659 }
660 // Write new message
661 frame_sel.insert(ptr, 0);
662 }
663 }
664 fclose(fp);
665 }
666 else
667 {
668 // Title only
669 frame_sel.init(FRAME_BUFF_SIZE);
670 snprintf(frame_sel.title, 32, "Cri SEL");
671 frame_sel.mtime = 0;
672 }
673
674 if (page > frame_sel.pages)
675 {
676 return -1;
677 }
678
Vijay Khemka63c99be2020-05-27 19:14:35 -0700679 ret = frame_sel.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800680 if (ret < 0)
681 {
682 *count = 0;
683 return -1;
684 }
685 *count = (uint8_t)ret;
686
687 if (page < frame_sel.pages)
688 *next = page + 1;
689 else
690 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
691 // last page
692
693 return 0;
694}
695
Willy Tue39f9392022-06-15 13:24:20 -0700696static int udbg_get_cri_sensor(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700697 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800698{
Vijay Khemka427b2762019-12-12 12:49:25 -0800699 int ret;
700 double fvalue;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530701 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800702
703 if (page == 1)
704 {
705 // Only update frame data while getting page 1
706
707 // initialize and clear frame
708 frame_snr.init(FRAME_BUFF_SIZE);
709 snprintf(frame_snr.title, 32, "CriSensor");
Vijay Khemka427b2762019-12-12 12:49:25 -0800710
711 nlohmann::json senObj;
712
713 /* Get critical sensor names stored in json file */
714 std::ifstream file(JSON_SENSOR_NAMES_FILE);
715 if (file)
716 {
717 file >> senObj;
718 file.close();
719 }
720 else
721 {
722 phosphor::logging::log<phosphor::logging::level::ERR>(
723 "Critical Sensor names file not found",
724 phosphor::logging::entry("CRI_SENSOR_NAMES_FILE=%s",
725 JSON_SENSOR_NAMES_FILE));
726 return -1;
727 }
728
729 /* Get sensors values for all critical sensors */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700730 for (auto& j : senObj.items())
Vijay Khemka427b2762019-12-12 12:49:25 -0800731 {
732 std::string senName = j.key();
733 auto val = j.value();
734
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530735 if (senName[0] == '_')
736 {
737 senName = std::to_string(pos) + senName;
738 }
739
Vijay Khemka427b2762019-12-12 12:49:25 -0800740 if (ipmi::storage::getSensorValue(senName, fvalue) == 0)
741 {
742 std::stringstream ss;
Vijay Khemkaf43fad42019-12-26 11:47:58 -0800743 int prec = 0; // Default value
744
745 if (val.find("precision") != val.end())
746 prec = val["precision"];
747
748 ss << std::fixed << std::setprecision(prec) << fvalue;
Vijay Khemka427b2762019-12-12 12:49:25 -0800749
750 std::string senStr;
751 if (val.find("short_name") != val.end())
752 senStr = val["short_name"];
753 else
754 senStr = senName;
755
756 senStr += ss.str();
Vijay Khemka58bd5d82019-12-13 11:05:56 -0800757
758 /* Get unit string for sensor and append in output */
759 std::string unitStr;
760 if (ipmi::storage::getSensorUnit(senName, unitStr) == 0)
761 senStr += unitStr;
762
Vijay Khemka427b2762019-12-12 12:49:25 -0800763 frame_snr.append(senStr.c_str(), 0);
764 }
765 else
766 {
767 phosphor::logging::log<phosphor::logging::level::INFO>(
768 "Critical sensor not found",
769 phosphor::logging::entry("CRI_SENSOR_NAME=%s",
770 senName.c_str()));
771 }
772 }
773
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800774 } // End of update frame
775
776 if (page > frame_snr.pages)
777 {
778 return -1;
779 }
780
Vijay Khemka63c99be2020-05-27 19:14:35 -0700781 ret = frame_snr.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800782 if (ret < 0)
783 {
784 *count = 0;
785 return -1;
786 }
787 *count = (uint8_t)ret;
788
789 if (page < frame_snr.pages)
790 *next = page + 1;
791 else
792 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
793 // last page
794
795 return 0;
796}
797
Vijay Khemka63c99be2020-05-27 19:14:35 -0700798static int getBiosVer(std::string& ver)
Vijay Khemka88884b82019-08-27 15:23:07 -0700799{
800 nlohmann::json appObj;
801
802 std::ifstream file(JSON_APP_DATA_FILE);
803 if (file)
804 {
805 file >> appObj;
806 file.close();
807 if (appObj.find(KEY_SYSFW_VER) != appObj.end())
808 {
809 ver = appObj[KEY_SYSFW_VER].get<std::string>();
810 return 0;
811 }
812 }
813
814 return -1;
815}
816
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530817int sendBicCmd(uint8_t netFn, uint8_t cmd, uint8_t bicAddr,
818 std::vector<uint8_t>& cmdData, std::vector<uint8_t>& respData)
819{
820 static constexpr uint8_t lun = 0;
821
822 auto bus = getSdBus();
823
824 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
825 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
826 "org.openbmc.Ipmb", "sendRequest");
827 method.append(bicAddr, netFn, lun, cmd, cmdData);
828
829 auto reply = bus->call(method);
830 if (reply.is_method_error())
831 {
832 phosphor::logging::log<phosphor::logging::level::ERR>(
833 "Error reading from BIC");
834 return -1;
835 }
836
837 IpmbMethodType resp;
838 reply.read(resp);
839
840 respData =
841 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
842
843 return 0;
844}
845
Vijay Khemka63c99be2020-05-27 19:14:35 -0700846int sendMeCmd(uint8_t netFn, uint8_t cmd, std::vector<uint8_t>& cmdData,
847 std::vector<uint8_t>& respData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -0700848{
849 auto bus = getSdBus();
850
851 if (DEBUG)
852 {
853 std::cout << "ME NetFn:cmd " << (int)netFn << ":" << (int)cmd << "\n";
854 std::cout << "ME req data: ";
855 for (auto d : cmdData)
856 {
857 std::cout << d << " ";
858 }
859 std::cout << "\n";
860 }
861
862 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
863 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
864 "org.openbmc.Ipmb", "sendRequest");
865 method.append(meAddress, netFn, lun, cmd, cmdData);
866
867 auto reply = bus->call(method);
868 if (reply.is_method_error())
869 {
870 phosphor::logging::log<phosphor::logging::level::ERR>(
871 "Error reading from ME");
872 return -1;
873 }
874
875 IpmbMethodType resp;
876 reply.read(resp);
877
878 respData =
879 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
880
881 if (DEBUG)
882 {
883 std::cout << "ME resp data: ";
884 for (auto d : respData)
885 {
886 std::cout << d << " ";
887 }
888 std::cout << "\n";
889 }
890
891 return 0;
892}
893
Potin Lai2ad53982022-10-27 17:02:51 +0800894#ifdef ME_SUPPORT
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530895static int getMeStatus(std::string& status, size_t pos)
Vijay Khemka317999d2020-01-02 13:43:42 -0800896{
897 uint8_t cmd = 0x01; // Get Device id command
898 uint8_t netFn = 0x06; // Netfn for APP
899 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
900 std::vector<uint8_t> cmdData;
901
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530902 uint8_t meAddr = meAddress;
903 bool platform = isMultiHostPlatform();
904 if (platform == true)
905 {
906 meAddr = ((pos - 1) << 2);
907 }
908
Vijay Khemka317999d2020-01-02 13:43:42 -0800909 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
910 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
911 "org.openbmc.Ipmb", "sendRequest");
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530912 method.append(meAddr, netFn, lun, cmd, cmdData);
Vijay Khemka317999d2020-01-02 13:43:42 -0800913
914 auto reply = bus->call(method);
915 if (reply.is_method_error())
916 {
917 std::cerr << "Error reading from ME\n";
918 return -1;
919 }
920
921 IpmbMethodType resp;
922 reply.read(resp);
923
924 std::vector<uint8_t> data;
925 data = std::get<5>(resp);
926
927 if (DEBUG)
928 {
929 std::cout << "ME Get ID: ";
930 for (size_t d : data)
931 {
932 std::cout << d << " ";
933 }
934 std::cout << "\n";
935 }
936
937 if (data[2] & 0x80)
938 status = "recovery mode";
939 else
940 status = "operation mode";
941
942 return 0;
943}
Potin Lai2ad53982022-10-27 17:02:51 +0800944#endif
Vijay Khemka317999d2020-01-02 13:43:42 -0800945
Willy Tue39f9392022-06-15 13:24:20 -0700946static int udbg_get_info_page(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700947 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800948{
Willy Tue39f9392022-06-15 13:24:20 -0700949 char line_buff[1000];
950 [[maybe_unused]] char* pres_dev = line_buff;
951 [[maybe_unused]] size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800952 int ret;
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530953 std::string serialName = "SerialNumber";
954 std::string partName = "PartNumber";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800955 std::string verDel = "VERSION=";
956 std::string verPath = "/etc/os-release";
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530957 size_t hostPosition;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800958
959 if (page == 1)
960 {
961 // Only update frame data while getting page 1
962
963 // initialize and clear frame
964 frame_info.init(FRAME_BUFF_SIZE);
965 snprintf(frame_info.title, 32, "SYS_Info");
966
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530967 bool platform = isMultiHostPlatform();
968 if (platform == true)
969 {
970 hostPosition = getSelectorPosition();
971 }
972
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530973 if (hostPosition == BMC_POSITION || hostInstances == "0")
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530974 {
975 frame_info.append("FRU:spb", 0);
976 }
Potin Laif24c78e2022-10-27 17:13:14 +0800977 else if (hostPosition != BMC_POSITION &&
978 hostPosition <= getMaxHostPosition())
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530979 {
980 std::string data = "FRU:slot" + std::to_string(hostPosition);
981 frame_info.append(data.c_str(), 0);
982 }
983
984 // FRU
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800985 std::string data;
986 frame_info.append("SN:", 0);
987 if (getFruData(data, serialName) != 0)
988 {
989 data = "Not Found";
990 }
991 frame_info.append(data.c_str(), 1);
992 frame_info.append("PN:", 0);
993 if (getFruData(data, partName) != 0)
994 {
995 data = "Not Found";
996 }
997 frame_info.append(data.c_str(), 1);
998
999 // LAN
1000 getNetworkData(3, line_buff);
1001 frame_info.append("BMC_IP:", 0);
1002 frame_info.append(line_buff, 1);
1003 getNetworkData(59, line_buff);
1004 frame_info.append("BMC_IPv6:", 0);
1005 frame_info.append(line_buff, 1);
1006
1007 // BMC ver
1008 std::ifstream file(verPath);
1009 if (file)
1010 {
1011 std::string line;
1012 while (std::getline(file, line))
1013 {
1014 if (line.find(verDel) != std::string::npos)
1015 {
1016 std::string bmcVer = line.substr(verDel.size());
1017 frame_info.append("BMC_FW_ver:", 0);
1018 frame_info.append(bmcVer.c_str(), 1);
1019 break;
1020 }
1021 }
1022 }
1023
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301024 if (hostPosition != BMC_POSITION)
Vijay Khemka88884b82019-08-27 15:23:07 -07001025 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301026 // BIOS ver
1027 std::string biosVer;
1028 if (getBiosVer(biosVer) == 0)
1029 {
1030 frame_info.append("BIOS_FW_ver:", 0);
1031 frame_info.append(biosVer.c_str(), 1);
1032 }
Potin Lai2ad53982022-10-27 17:02:51 +08001033
1034#ifdef ME_SUPPORT
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301035 // ME status
1036 std::string meStatus;
1037 if (getMeStatus(meStatus, pos) != 0)
1038 {
1039 phosphor::logging::log<phosphor::logging::level::WARNING>(
1040 "Reading ME status failed");
1041 meStatus = "unknown";
1042 }
1043 frame_info.append("ME_status:", 0);
1044 frame_info.append(meStatus.c_str(), 1);
Potin Lai2ad53982022-10-27 17:02:51 +08001045#endif
Vijay Khemka88884b82019-08-27 15:23:07 -07001046 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001047
Vijay Khemka317999d2020-01-02 13:43:42 -08001048 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001049 // Board ID
1050
1051 // Battery - Use Escape sequence
1052 frame_info.append("Battery:", 0);
1053 frame_info.append(ESC_BAT " ", 1);
1054 // frame_info.append(&frame_info, esc_bat, 1);
1055
1056 // MCU Version - Use Escape sequence
1057 frame_info.append("MCUbl_ver:", 0);
1058 frame_info.append(ESC_MCU_BL_VER, 1);
1059 frame_info.append("MCU_ver:", 0);
1060 frame_info.append(ESC_MCU_RUN_VER, 1);
1061
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001062 // Sys config present device
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301063 if (hostPosition != BMC_POSITION)
1064 {
1065 frame_info.append("Sys Conf. info:", 0);
1066
1067 // Dimm info
1068 std::vector<std::string> data;
1069 sysConfig(data, pos);
1070 for (auto& info : data)
1071 {
1072 frame_info.append(info.c_str(), 1);
1073 }
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301074
1075 // Processor info
1076 std::string result;
1077 procInfo(result, pos);
1078 frame_info.append(result.c_str(), 1);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301079 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001080
1081 } // End of update frame
1082
1083 if (page > frame_info.pages)
1084 {
1085 return -1;
1086 }
1087
Vijay Khemka63c99be2020-05-27 19:14:35 -07001088 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001089 if (ret < 0)
1090 {
1091 *count = 0;
1092 return -1;
1093 }
1094 *count = (uint8_t)ret;
1095
1096 if (page < frame_info.pages)
1097 *next = page + 1;
1098 else
1099 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
1100 // last page
1101
1102 return 0;
1103}
1104
Vijay Khemka63c99be2020-05-27 19:14:35 -07001105int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
1106 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001107{
1108 switch (frame)
1109 {
1110 case 1: // info_page
1111 return udbg_get_info_page(frame, page, next, count, buffer);
1112 case 2: // critical SEL
1113 return udbg_get_cri_sel(frame, page, next, count, buffer);
1114 case 3: // critical Sensor
1115 return udbg_get_cri_sensor(frame, page, next, count, buffer);
1116 default:
1117 return -1;
1118 }
1119}
1120
1121static uint8_t panel_main(uint8_t item)
1122{
1123 // Update item list when select item 0
1124 switch (item)
1125 {
1126 case 1:
1127 return panels[PANEL_BOOT_ORDER].select(0);
1128 case 2:
1129 return panels[PANEL_POWER_POLICY].select(0);
1130 default:
1131 return PANEL_MAIN;
1132 }
1133}
1134
Willy Tue39f9392022-06-15 13:24:20 -07001135static uint8_t panel_boot_order(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001136{
Willy Tue39f9392022-06-15 13:24:20 -07001137 /* To be implemented */
1138#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001139 int i;
1140 unsigned char buff[MAX_VALUE_LEN], pickup, len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301141 size_t pos = plat_get_fru_sel();
Willy Tue39f9392022-06-15 13:24:20 -07001142 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
1143 {
1144 if (item > 0 && item < SIZE_BOOT_ORDER)
1145 {
1146 pickup = buff[item];
1147 while (item > 1)
1148 {
1149 buff[item] = buff[item - 1];
1150 item--;
1151 }
1152 buff[item] = pickup;
1153 buff[0] |= 0x80;
1154 pal_set_boot_order(pos, buff, buff, &len);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001155
Willy Tue39f9392022-06-15 13:24:20 -07001156 // refresh items
1157 return panels[PANEL_BOOT_ORDER].select(0);
1158 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001159
Willy Tue39f9392022-06-15 13:24:20 -07001160 // '*': boot flags valid, BIOS has not yet read
1161 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32, "Boot Order%c",
1162 (buff[0] & 0x80) ? '*' : '\0');
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001163
Willy Tue39f9392022-06-15 13:24:20 -07001164 for (i = 1; i < SIZE_BOOT_ORDER; i++)
1165 {
1166 switch (buff[i])
1167 {
1168 case 0x0:
1169 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1170 " USB device");
1171 break;
1172 case 0x1:
1173 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1174 " Network v4");
1175 break;
1176 case (0x1 | 0x8):
1177 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1178 " Network v6");
1179 break;
1180 case 0x2:
1181 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1182 " SATA HDD");
1183 break;
1184 case 0x3:
1185 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1186 " SATA-CDROM");
1187 break;
1188 case 0x4:
1189 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1190 " Other");
1191 break;
1192 default:
1193 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
1194 break;
1195 }
1196 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001197
Willy Tue39f9392022-06-15 13:24:20 -07001198 // remove empty items
1199 for (i--;
1200 (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0);
1201 i--)
1202 ;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001203
Willy Tue39f9392022-06-15 13:24:20 -07001204 panels[PANEL_BOOT_ORDER].item_num = i;
1205 }
1206 else
1207 {
1208 panels[PANEL_BOOT_ORDER].item_num = 0;
1209 }
1210#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001211 return PANEL_BOOT_ORDER;
1212}
1213
Willy Tue39f9392022-06-15 13:24:20 -07001214static uint8_t panel_power_policy(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001215{
Willy Tue39f9392022-06-15 13:24:20 -07001216/* To be cleaned */
1217#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001218 uint8_t buff[32] = {0};
1219 uint8_t res_len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301220 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001221 uint8_t policy;
Willy Tue39f9392022-06-15 13:24:20 -07001222 uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1223 POWER_CFG_OFF};
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001224
Willy Tue39f9392022-06-15 13:24:20 -07001225 if (pos != FRU_ALL)
1226 {
1227 if (item > 0 && item <= sizeof(pwr_policy_item_map))
1228 {
1229 policy = pwr_policy_item_map[item - 1];
1230 pal_set_power_restore_policy(pos, &policy, NULL);
1231 }
1232 pal_get_chassis_status(pos, NULL, buff, &res_len);
1233 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1234 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32, "%cPower On",
1235 policy == POWER_CFG_ON ? '*' : ' ');
1236 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32, "%cLast State",
1237 policy == POWER_CFG_LPS ? '*' : ' ');
1238 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32, "%cPower Off",
1239 policy == POWER_CFG_OFF ? '*' : ' ');
1240 panels[PANEL_POWER_POLICY].item_num = 3;
1241 }
1242 else
1243 {
1244 panels[PANEL_POWER_POLICY].item_num = 0;
1245 }
1246#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001247 return PANEL_POWER_POLICY;
1248}
1249
1250int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001251 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001252{
1253 if (panel > panelNum || panel < PANEL_MAIN)
1254 return IPMI_CC_PARM_OUT_OF_RANGE;
1255
1256 // No more item; End of item list
1257 if (item > panels[panel].item_num)
1258 return IPMI_CC_PARM_OUT_OF_RANGE;
1259
1260 switch (operation)
1261 {
1262 case 0: // Get Description
1263 break;
1264 case 1: // Select item
1265 panel = panels[panel].select(item);
1266 item = 0;
1267 break;
1268 case 2: // Back
1269 panel = panels[panel].parent;
1270 item = 0;
1271 break;
1272 default:
1273 return IPMI_CC_PARM_OUT_OF_RANGE;
1274 }
1275
1276 buffer[0] = panel;
1277 buffer[1] = item;
1278 buffer[2] = strlen(panels[panel].item_str[item]);
1279 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1280 {
1281 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1282 }
1283 *count = buffer[2] + 3;
1284 return IPMI_CC_OK;
1285}
1286
1287} // end of namespace ipmi