blob: b886525d25c5ee3369cf46ca105c67b7d067914a [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);
Vijay Khemkae7d23d02019-03-08 13:13:40 -080026
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053027bool isMultiHostPlatform();
28
29/* Declare Host Selector interface and path */
30namespace selector
31{
32const std::string path = "/xyz/openbmc_project/Chassis/Buttons/HostSelector";
33const std::string interface =
34 "xyz.openbmc_project.Chassis.HostSelector.Selector";
35const std::string propertyName = "Position";
36} // namespace selector
37
Vijay Khemka427b2762019-12-12 12:49:25 -080038/* Declare storage functions used here */
39namespace storage
40{
Vijay Khemka63c99be2020-05-27 19:14:35 -070041int getSensorValue(std::string&, double&);
42int getSensorUnit(std::string&, std::string&);
Vijay Khemka58bd5d82019-12-13 11:05:56 -080043} // namespace storage
Vijay Khemka427b2762019-12-12 12:49:25 -080044
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053045size_t getSelectorPosition()
46{
47 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
48 std::string service =
49 getService(*dbus, ipmi::selector::interface, ipmi::selector::path);
50 Value variant = getDbusProperty(*dbus, service, ipmi::selector::path,
51 ipmi::selector::interface,
52 ipmi::selector::propertyName);
53 size_t result = std::get<size_t>(variant);
54 return result;
55}
56
Vijay Khemkae7d23d02019-03-08 13:13:40 -080057static int panelNum = (sizeof(panels) / sizeof(struct ctrl_panel)) - 1;
58
59/* Returns the FRU the hand-switch is switched to. If it is switched to BMC
60 * it returns FRU_ALL. Note, if in err, it returns FRU_ALL */
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053061static size_t plat_get_fru_sel()
Vijay Khemkae7d23d02019-03-08 13:13:40 -080062{
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053063 size_t position;
64 bool platform = isMultiHostPlatform();
65
66 if (platform == true)
67 {
68 try
69 {
70 size_t hostPosition = getSelectorPosition();
71 position = hostPosition;
72 if (position == BMC_POSITION)
73 {
74 return FRU_ALL;
75 }
76 }
77 catch (...)
78 {
79 std::cout << "Error reading host selector position" << std::endl;
80 }
81 }
82 else
83 {
84 // For Tiogapass it just return 1, can modify to support more platform
85 position = 1;
86 }
87 return position;
Vijay Khemkae7d23d02019-03-08 13:13:40 -080088}
89
90// return 0 on seccuess
91int frame::init(size_t size)
92{
93 // Reset status
94 idx_head = idx_tail = 0;
95 lines = 0;
96 esc_sts = 0;
97 pages = 1;
98
99 if (buf != NULL && max_size == size)
100 {
101 // reinit
102 return 0;
103 }
104
105 if (buf != NULL && max_size != size)
106 {
107 delete[] buf;
108 }
109 // Initialize Configuration
110 title[0] = '\0';
111 buf = new char[size];
112 max_size = size;
113 max_page = size;
114 line_per_page = 7;
115 line_width = 16;
116 overwrite = 0;
117
118 if (buf)
119 return 0;
120 else
121 return -1;
122}
123
124// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700125int frame::append(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800126{
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530127 const size_t buf_size = 128;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800128 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700129 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800130 int ret;
131
132 ret = parse(lbuf, buf_size, string, indent);
133
134 if (ret < 0)
135 return ret;
136
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800137 for (ptr = lbuf; *ptr != '\0'; ptr++)
138 {
139 if (isFull())
140 {
141 if (overwrite)
142 {
143 if (buf[idx_head] == LINE_DELIMITER)
144 lines--;
145 idx_head = (idx_head + 1) % max_size;
146 }
147 else
148 return -1;
149 }
150
151 buf[idx_tail] = *ptr;
152 if (*ptr == LINE_DELIMITER)
153 lines++;
154
155 idx_tail = (idx_tail + 1) % max_size;
156 }
157
158 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
159
160 if (pages > max_page)
161 pages = max_page;
162
163 return 0;
164}
165
166// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700167int frame::insert(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800168{
169 const size_t buf_size = 128;
170 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700171 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800172 int ret;
173 int i;
174
175 ret = parse(lbuf, buf_size, string, indent);
176
177 if (ret < 0)
178 return ret;
179
180 for (i = strlen(lbuf) - 1; i >= 0; i--)
181 {
182 ptr = &lbuf[i];
183 if (isFull())
184 {
185 if (overwrite)
186 {
187 idx_tail = (idx_tail + max_size - 1) % max_size;
188 if (buf[idx_tail] == LINE_DELIMITER)
189 lines--;
190 }
191 else
192 return -1;
193 }
194
195 idx_head = (idx_head + max_size - 1) % max_size;
196
197 buf[idx_head] = *ptr;
198 if (*ptr == LINE_DELIMITER)
199 lines++;
200 }
201
202 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
203
204 if (pages > max_page)
205 pages = max_page;
206
207 return 0;
208}
209
210// return page size
Vijay Khemka63c99be2020-05-27 19:14:35 -0700211int frame::getPage(int page, char* page_buf, size_t page_buf_size)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800212{
213 int ret;
214 uint16_t line = 0;
215 uint16_t idx, len;
216
217 if (buf == NULL)
218 return -1;
219
220 // 1-based page
221 if (page > pages || page < 1)
222 return -1;
223
Willy Tue39f9392022-06-15 13:24:20 -0700224 if (page_buf == NULL || page_buf_size == 0)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800225 return -1;
226
227 ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages);
228 len = strlen(page_buf);
229 if (ret < 0)
230 return -1;
231
232 line = 0;
233 idx = idx_head;
234 while (line < ((page - 1) * line_per_page) && idx != idx_tail)
235 {
236 if (buf[idx] == LINE_DELIMITER)
237 line++;
238 idx = (idx + 1) % max_size;
239 }
240
241 while (line < ((page)*line_per_page) && idx != idx_tail)
242 {
243 if (buf[idx] == LINE_DELIMITER)
244 {
245 line++;
246 }
247 else
248 {
249 page_buf[len++] = buf[idx];
250 if (len == (page_buf_size - 1))
251 {
252 break;
253 }
254 }
255 idx = (idx + 1) % max_size;
256 }
257
258 return len;
259}
260
261// return 1 for frame buffer full
262int frame::isFull()
263{
264 if (buf == NULL)
265 return -1;
266
267 if ((idx_tail + 1) % max_size == idx_head)
268 return 1;
269 else
270 return 0;
271}
272
273// return 1 for Escape Sequence
274int frame::isEscSeq(char chr)
275{
276 uint8_t curr_sts = esc_sts;
277
278 if (esc_sts == 0 && (chr == 0x1b))
279 esc_sts = 1; // Escape Sequence
280 else if (esc_sts == 1 && (chr == 0x5b))
281 esc_sts = 2; // Control Sequence Introducer(CSI)
282 else if (esc_sts == 1 && (chr != 0x5b))
283 esc_sts = 0;
284 else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e))
285 esc_sts = 0;
286
287 if (curr_sts || esc_sts)
288 return 1;
289 else
290 return 0;
291}
292
293// return 0 on success
Vijay Khemka63c99be2020-05-27 19:14:35 -0700294int frame::parse(char* lbuf, size_t buf_size, const char* input, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800295{
296 uint8_t pos, esc;
Willy Tue39f9392022-06-15 13:24:20 -0700297 size_t i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800298 const char *in, *end;
299
300 if (buf == NULL || input == NULL)
301 return -1;
302
303 if (indent >= line_width || indent < 0)
304 return -1;
305
306 in = input;
307 end = in + strlen(input);
308 pos = 0; // line position
309 esc = 0; // escape state
310 i = 0; // buf index
311 while (in != end)
312 {
313 if (i >= buf_size)
314 break;
315
316 if (pos < indent)
317 {
318 // fill indent
319 lbuf[i++] = ' ';
320 pos++;
321 continue;
322 }
323
324 esc = isEscSeq(*in);
325
326 if (!esc && pos == line_width)
327 {
328 lbuf[i++] = LINE_DELIMITER;
329 pos = 0;
330 continue;
331 }
332
333 if (!esc)
334 pos++;
335
336 // fill input data
337 lbuf[i++] = *(in++);
338 }
339
340 // padding
341 while (pos <= line_width)
342 {
343 if (i >= buf_size)
344 break;
345 if (pos < line_width)
346 lbuf[i++] = ' ';
347 else
348 lbuf[i++] = LINE_DELIMITER;
349 pos++;
350 }
351
352 // full
353 if (i >= buf_size)
354 return -1;
355
356 lbuf[i++] = '\0';
357
358 return 0;
359}
360
Vijay Khemka63c99be2020-05-27 19:14:35 -0700361static int chk_cri_sel_update(uint8_t* cri_sel_up)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800362{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700363 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800364 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530365 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800366 static uint8_t pre_pos = 0xff;
367
368 fp = fopen("/mnt/data/cri_sel", "r");
369 if (fp)
370 {
371 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
372 (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos))
373 {
374 *cri_sel_up = 1;
375 }
376 else
377 {
378 *cri_sel_up = 0;
379 }
380 fclose(fp);
381 }
382 else
383 {
384 if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos)
385 {
386 *cri_sel_up = 1;
387 }
388 else
389 {
390 *cri_sel_up = 0;
391 }
392 }
393 pre_pos = pos;
394 return 0;
395}
396
Vijay Khemka63c99be2020-05-27 19:14:35 -0700397int plat_udbg_get_frame_info(uint8_t* num)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800398{
399 *num = 3;
400 return 0;
401}
402
Vijay Khemka63c99be2020-05-27 19:14:35 -0700403int plat_udbg_get_updated_frames(uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800404{
405 uint8_t cri_sel_up = 0;
406 uint8_t info_page_up = 1;
407
408 *count = 0;
409
410 // info page update
411 if (info_page_up == 1)
412 {
413 buffer[*count] = 1;
414 *count += 1;
415 }
416
417 // cri sel update
418 chk_cri_sel_update(&cri_sel_up);
419 if (cri_sel_up == 1)
420 {
421 buffer[*count] = 2;
422 *count += 1;
423 }
424
425 // cri sensor update
426 buffer[*count] = 3;
427 *count += 1;
428
429 return 0;
430}
431
Vijay Khemka63c99be2020-05-27 19:14:35 -0700432int plat_udbg_get_post_desc(uint8_t index, uint8_t* next, uint8_t phase,
433 uint8_t* end, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800434{
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700435 nlohmann::json postObj;
436 std::string postCode;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800437
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700438 /* Get post description data stored in json file */
439 std::ifstream file(JSON_POST_DATA_FILE);
440 if (file)
441 {
442 file >> postObj;
443 file.close();
444 }
445 else
446 {
447 phosphor::logging::log<phosphor::logging::level::ERR>(
448 "Post code description file not found",
449 phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE));
450 return -1;
451 }
452
453 std::string phaseStr = "PhaseAny";
454 if (postObj.find(phaseStr) == postObj.end())
455 {
456 phaseStr = "Phase" + std::to_string(phase);
457 }
458
459 if (postObj.find(phaseStr) == postObj.end())
460 {
461 phosphor::logging::log<phosphor::logging::level::ERR>(
462 "Post code phase not available",
463 phosphor::logging::entry("PHASE=%d", phase));
464 return -1;
465 }
466
467 auto phaseObj = postObj[phaseStr];
468 int phaseSize = phaseObj.size();
469
470 for (int i = 0; i < phaseSize; i++)
471 {
472 postCode = phaseObj[i][0];
473 if (index == stoul(postCode, nullptr, 16))
474 {
475 std::string postDesc = phaseObj[i][1];
476 *length = postDesc.size();
477 memcpy(buffer, postDesc.data(), *length);
478 buffer[*length] = '\0';
479
480 if (phaseSize != i + 1)
481 {
482 postCode = phaseObj[i + 1][0];
483 *next = stoul(postCode, nullptr, 16);
484 *end = 0;
485 }
486 else
487 {
488 if (postObj.size() != phase)
489 {
490 std::string nextPhaseStr =
491 "Phase" + std::to_string(phase + 1);
492 postCode = postObj[nextPhaseStr][0][0];
493 *next = stoul(postCode, nullptr, 16);
494 *end = 0;
495 }
496 else
497 {
498 *next = 0xff;
499 *end = 1;
500 }
501 }
502
503 return 0;
504 }
505 }
506
507 phosphor::logging::log<phosphor::logging::level::ERR>(
508 "Post code description data not available",
509 phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index));
510 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800511}
512
Vijay Khemka63c99be2020-05-27 19:14:35 -0700513int plat_udbg_get_gpio_desc(uint8_t index, uint8_t* next, uint8_t* level,
514 uint8_t* def, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800515{
Vijay Khemka38183d62019-08-28 16:19:33 -0700516 nlohmann::json gpioObj;
517 std::string gpioPin;
518
519 /* Get gpio data stored in json file */
520 std::ifstream file(JSON_GPIO_DATA_FILE);
521 if (file)
522 {
523 file >> gpioObj;
524 file.close();
525 }
526 else
527 {
528 phosphor::logging::log<phosphor::logging::level::ERR>(
529 "GPIO pin description file not found",
530 phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s",
531 JSON_GPIO_DATA_FILE));
532 return -1;
533 }
534
535 if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end())
536 {
537 phosphor::logging::log<phosphor::logging::level::ERR>(
538 "GPIO pin details not available",
539 phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY));
540 return -1;
541 }
542
543 auto obj = gpioObj[DEBUG_GPIO_KEY];
544 int objSize = obj.size();
545
546 for (int i = 0; i < objSize; i++)
547 {
548 if (obj[i].size() != GPIO_ARRAY_SIZE)
549 {
550 phosphor::logging::log<phosphor::logging::level::ERR>(
551 "Size of gpio array is incorrect",
552 phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE));
553 return -1;
554 }
555
556 gpioPin = obj[i][GPIO_PIN_INDEX];
557 if (index == stoul(gpioPin, nullptr, 16))
558 {
559 if (objSize != i + 1)
560 {
561 gpioPin = obj[i + 1][GPIO_PIN_INDEX];
562 *next = stoul(gpioPin, nullptr, 16);
563 }
564 else
565 {
566 *next = 0xff;
567 }
568
569 *level = obj[i][GPIO_LEVEL_INDEX];
570 *def = obj[i][GPIO_DEF_INDEX];
571 std::string gpioDesc = obj[i][GPIO_DESC_INDEX];
572 *length = gpioDesc.size();
573 memcpy(buffer, gpioDesc.data(), *length);
574 buffer[*length] = '\0';
575
576 return 0;
577 }
578 }
579
580 phosphor::logging::log<phosphor::logging::level::ERR>(
581 "GPIO pin description data not available",
582 phosphor::logging::entry("GPIO_PIN=0x%x", index));
583 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800584}
585
Willy Tue39f9392022-06-15 13:24:20 -0700586static int udbg_get_cri_sel(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700587 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800588{
589 int len;
590 int ret;
Willy Tue39f9392022-06-15 13:24:20 -0700591 char line_buff[FRAME_PAGE_BUF_SIZE];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700592 const char* ptr;
593 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800594 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530595 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800596 static uint8_t pre_pos = FRU_ALL;
597 bool pos_changed = pre_pos != pos;
598
599 pre_pos = pos;
600
601 /* Revisit this */
602 fp = fopen("/mnt/data/cri_sel", "r");
603 if (fp)
604 {
605 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
606 (file_stat.st_mtime != frame_sel.mtime || pos_changed))
607 {
608 // initialize and clear frame
609 frame_sel.init(FRAME_BUFF_SIZE);
610 frame_sel.overwrite = 1;
611 frame_sel.max_page = 20;
612 frame_sel.mtime = file_stat.st_mtime;
613 snprintf(frame_sel.title, 32, "Cri SEL");
614
615 while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp))
616 {
617 // Remove newline
618 line_buff[strlen(line_buff) - 1] = '\0';
619 ptr = line_buff;
620 // Find message
621 ptr = strstr(ptr, "local0.err");
622 if (ptr == NULL)
623 {
624 continue;
625 }
626
627 if ((ptr = strrchr(ptr, ':')) == NULL)
628 {
629 continue;
630 }
631 len = strlen(ptr);
632 if (len > 2)
633 {
634 // to skip log string ": "
635 ptr += 2;
636 }
637 // Write new message
638 frame_sel.insert(ptr, 0);
639 }
640 }
641 fclose(fp);
642 }
643 else
644 {
645 // Title only
646 frame_sel.init(FRAME_BUFF_SIZE);
647 snprintf(frame_sel.title, 32, "Cri SEL");
648 frame_sel.mtime = 0;
649 }
650
651 if (page > frame_sel.pages)
652 {
653 return -1;
654 }
655
Vijay Khemka63c99be2020-05-27 19:14:35 -0700656 ret = frame_sel.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800657 if (ret < 0)
658 {
659 *count = 0;
660 return -1;
661 }
662 *count = (uint8_t)ret;
663
664 if (page < frame_sel.pages)
665 *next = page + 1;
666 else
667 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
668 // last page
669
670 return 0;
671}
672
Willy Tue39f9392022-06-15 13:24:20 -0700673static int udbg_get_cri_sensor(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700674 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800675{
Vijay Khemka427b2762019-12-12 12:49:25 -0800676 int ret;
677 double fvalue;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530678 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800679
680 if (page == 1)
681 {
682 // Only update frame data while getting page 1
683
684 // initialize and clear frame
685 frame_snr.init(FRAME_BUFF_SIZE);
686 snprintf(frame_snr.title, 32, "CriSensor");
Vijay Khemka427b2762019-12-12 12:49:25 -0800687
688 nlohmann::json senObj;
689
690 /* Get critical sensor names stored in json file */
691 std::ifstream file(JSON_SENSOR_NAMES_FILE);
692 if (file)
693 {
694 file >> senObj;
695 file.close();
696 }
697 else
698 {
699 phosphor::logging::log<phosphor::logging::level::ERR>(
700 "Critical Sensor names file not found",
701 phosphor::logging::entry("CRI_SENSOR_NAMES_FILE=%s",
702 JSON_SENSOR_NAMES_FILE));
703 return -1;
704 }
705
706 /* Get sensors values for all critical sensors */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700707 for (auto& j : senObj.items())
Vijay Khemka427b2762019-12-12 12:49:25 -0800708 {
709 std::string senName = j.key();
710 auto val = j.value();
711
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530712 if (senName[0] == '_')
713 {
714 senName = std::to_string(pos) + senName;
715 }
716
Vijay Khemka427b2762019-12-12 12:49:25 -0800717 if (ipmi::storage::getSensorValue(senName, fvalue) == 0)
718 {
719 std::stringstream ss;
Vijay Khemkaf43fad42019-12-26 11:47:58 -0800720 int prec = 0; // Default value
721
722 if (val.find("precision") != val.end())
723 prec = val["precision"];
724
725 ss << std::fixed << std::setprecision(prec) << fvalue;
Vijay Khemka427b2762019-12-12 12:49:25 -0800726
727 std::string senStr;
728 if (val.find("short_name") != val.end())
729 senStr = val["short_name"];
730 else
731 senStr = senName;
732
733 senStr += ss.str();
Vijay Khemka58bd5d82019-12-13 11:05:56 -0800734
735 /* Get unit string for sensor and append in output */
736 std::string unitStr;
737 if (ipmi::storage::getSensorUnit(senName, unitStr) == 0)
738 senStr += unitStr;
739
Vijay Khemka427b2762019-12-12 12:49:25 -0800740 frame_snr.append(senStr.c_str(), 0);
741 }
742 else
743 {
744 phosphor::logging::log<phosphor::logging::level::INFO>(
745 "Critical sensor not found",
746 phosphor::logging::entry("CRI_SENSOR_NAME=%s",
747 senName.c_str()));
748 }
749 }
750
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800751 } // End of update frame
752
753 if (page > frame_snr.pages)
754 {
755 return -1;
756 }
757
Vijay Khemka63c99be2020-05-27 19:14:35 -0700758 ret = frame_snr.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800759 if (ret < 0)
760 {
761 *count = 0;
762 return -1;
763 }
764 *count = (uint8_t)ret;
765
766 if (page < frame_snr.pages)
767 *next = page + 1;
768 else
769 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
770 // last page
771
772 return 0;
773}
774
Vijay Khemka63c99be2020-05-27 19:14:35 -0700775static int getBiosVer(std::string& ver)
Vijay Khemka88884b82019-08-27 15:23:07 -0700776{
777 nlohmann::json appObj;
778
779 std::ifstream file(JSON_APP_DATA_FILE);
780 if (file)
781 {
782 file >> appObj;
783 file.close();
784 if (appObj.find(KEY_SYSFW_VER) != appObj.end())
785 {
786 ver = appObj[KEY_SYSFW_VER].get<std::string>();
787 return 0;
788 }
789 }
790
791 return -1;
792}
793
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530794int sendBicCmd(uint8_t netFn, uint8_t cmd, uint8_t bicAddr,
795 std::vector<uint8_t>& cmdData, std::vector<uint8_t>& respData)
796{
797 static constexpr uint8_t lun = 0;
798
799 auto bus = getSdBus();
800
801 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
802 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
803 "org.openbmc.Ipmb", "sendRequest");
804 method.append(bicAddr, netFn, lun, cmd, cmdData);
805
806 auto reply = bus->call(method);
807 if (reply.is_method_error())
808 {
809 phosphor::logging::log<phosphor::logging::level::ERR>(
810 "Error reading from BIC");
811 return -1;
812 }
813
814 IpmbMethodType resp;
815 reply.read(resp);
816
817 respData =
818 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
819
820 return 0;
821}
822
Vijay Khemka63c99be2020-05-27 19:14:35 -0700823int sendMeCmd(uint8_t netFn, uint8_t cmd, std::vector<uint8_t>& cmdData,
824 std::vector<uint8_t>& respData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -0700825{
826 auto bus = getSdBus();
827
828 if (DEBUG)
829 {
830 std::cout << "ME NetFn:cmd " << (int)netFn << ":" << (int)cmd << "\n";
831 std::cout << "ME req data: ";
832 for (auto d : cmdData)
833 {
834 std::cout << d << " ";
835 }
836 std::cout << "\n";
837 }
838
839 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
840 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
841 "org.openbmc.Ipmb", "sendRequest");
842 method.append(meAddress, netFn, lun, cmd, cmdData);
843
844 auto reply = bus->call(method);
845 if (reply.is_method_error())
846 {
847 phosphor::logging::log<phosphor::logging::level::ERR>(
848 "Error reading from ME");
849 return -1;
850 }
851
852 IpmbMethodType resp;
853 reply.read(resp);
854
855 respData =
856 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
857
858 if (DEBUG)
859 {
860 std::cout << "ME resp data: ";
861 for (auto d : respData)
862 {
863 std::cout << d << " ";
864 }
865 std::cout << "\n";
866 }
867
868 return 0;
869}
870
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530871static int getMeStatus(std::string& status, size_t pos)
Vijay Khemka317999d2020-01-02 13:43:42 -0800872{
873 uint8_t cmd = 0x01; // Get Device id command
874 uint8_t netFn = 0x06; // Netfn for APP
875 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
876 std::vector<uint8_t> cmdData;
877
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530878 uint8_t meAddr = meAddress;
879 bool platform = isMultiHostPlatform();
880 if (platform == true)
881 {
882 meAddr = ((pos - 1) << 2);
883 }
884
Vijay Khemka317999d2020-01-02 13:43:42 -0800885 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
886 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
887 "org.openbmc.Ipmb", "sendRequest");
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530888 method.append(meAddr, netFn, lun, cmd, cmdData);
Vijay Khemka317999d2020-01-02 13:43:42 -0800889
890 auto reply = bus->call(method);
891 if (reply.is_method_error())
892 {
893 std::cerr << "Error reading from ME\n";
894 return -1;
895 }
896
897 IpmbMethodType resp;
898 reply.read(resp);
899
900 std::vector<uint8_t> data;
901 data = std::get<5>(resp);
902
903 if (DEBUG)
904 {
905 std::cout << "ME Get ID: ";
906 for (size_t d : data)
907 {
908 std::cout << d << " ";
909 }
910 std::cout << "\n";
911 }
912
913 if (data[2] & 0x80)
914 status = "recovery mode";
915 else
916 status = "operation mode";
917
918 return 0;
919}
920
Willy Tue39f9392022-06-15 13:24:20 -0700921static int udbg_get_info_page(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700922 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800923{
Willy Tue39f9392022-06-15 13:24:20 -0700924 char line_buff[1000];
925 [[maybe_unused]] char* pres_dev = line_buff;
926 [[maybe_unused]] size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800927 int ret;
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530928 std::string serialName = "SerialNumber";
929 std::string partName = "PartNumber";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800930 std::string verDel = "VERSION=";
931 std::string verPath = "/etc/os-release";
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530932 size_t hostPosition;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800933
934 if (page == 1)
935 {
936 // Only update frame data while getting page 1
937
938 // initialize and clear frame
939 frame_info.init(FRAME_BUFF_SIZE);
940 snprintf(frame_info.title, 32, "SYS_Info");
941
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530942 bool platform = isMultiHostPlatform();
943 if (platform == true)
944 {
945 hostPosition = getSelectorPosition();
946 }
947
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530948 if (hostPosition == BMC_POSITION || hostInstances == "0")
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530949 {
950 frame_info.append("FRU:spb", 0);
951 }
952 else if (hostPosition != BMC_POSITION && hostPosition <= MAX_HOST_POS)
953 {
954 std::string data = "FRU:slot" + std::to_string(hostPosition);
955 frame_info.append(data.c_str(), 0);
956 }
957
958 // FRU
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800959 std::string data;
960 frame_info.append("SN:", 0);
961 if (getFruData(data, serialName) != 0)
962 {
963 data = "Not Found";
964 }
965 frame_info.append(data.c_str(), 1);
966 frame_info.append("PN:", 0);
967 if (getFruData(data, partName) != 0)
968 {
969 data = "Not Found";
970 }
971 frame_info.append(data.c_str(), 1);
972
973 // LAN
974 getNetworkData(3, line_buff);
975 frame_info.append("BMC_IP:", 0);
976 frame_info.append(line_buff, 1);
977 getNetworkData(59, line_buff);
978 frame_info.append("BMC_IPv6:", 0);
979 frame_info.append(line_buff, 1);
980
981 // BMC ver
982 std::ifstream file(verPath);
983 if (file)
984 {
985 std::string line;
986 while (std::getline(file, line))
987 {
988 if (line.find(verDel) != std::string::npos)
989 {
990 std::string bmcVer = line.substr(verDel.size());
991 frame_info.append("BMC_FW_ver:", 0);
992 frame_info.append(bmcVer.c_str(), 1);
993 break;
994 }
995 }
996 }
997
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530998 if (hostPosition != BMC_POSITION)
Vijay Khemka88884b82019-08-27 15:23:07 -0700999 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301000 // BIOS ver
1001 std::string biosVer;
1002 if (getBiosVer(biosVer) == 0)
1003 {
1004 frame_info.append("BIOS_FW_ver:", 0);
1005 frame_info.append(biosVer.c_str(), 1);
1006 }
1007 // ME status
1008 std::string meStatus;
1009 if (getMeStatus(meStatus, pos) != 0)
1010 {
1011 phosphor::logging::log<phosphor::logging::level::WARNING>(
1012 "Reading ME status failed");
1013 meStatus = "unknown";
1014 }
1015 frame_info.append("ME_status:", 0);
1016 frame_info.append(meStatus.c_str(), 1);
Vijay Khemka88884b82019-08-27 15:23:07 -07001017 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001018
Vijay Khemka317999d2020-01-02 13:43:42 -08001019 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001020 // Board ID
1021
1022 // Battery - Use Escape sequence
1023 frame_info.append("Battery:", 0);
1024 frame_info.append(ESC_BAT " ", 1);
1025 // frame_info.append(&frame_info, esc_bat, 1);
1026
1027 // MCU Version - Use Escape sequence
1028 frame_info.append("MCUbl_ver:", 0);
1029 frame_info.append(ESC_MCU_BL_VER, 1);
1030 frame_info.append("MCU_ver:", 0);
1031 frame_info.append(ESC_MCU_RUN_VER, 1);
1032
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001033 // Sys config present device
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301034 if (hostPosition != BMC_POSITION)
1035 {
1036 frame_info.append("Sys Conf. info:", 0);
1037
1038 // Dimm info
1039 std::vector<std::string> data;
1040 sysConfig(data, pos);
1041 for (auto& info : data)
1042 {
1043 frame_info.append(info.c_str(), 1);
1044 }
1045 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001046
1047 } // End of update frame
1048
1049 if (page > frame_info.pages)
1050 {
1051 return -1;
1052 }
1053
Vijay Khemka63c99be2020-05-27 19:14:35 -07001054 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001055 if (ret < 0)
1056 {
1057 *count = 0;
1058 return -1;
1059 }
1060 *count = (uint8_t)ret;
1061
1062 if (page < frame_info.pages)
1063 *next = page + 1;
1064 else
1065 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
1066 // last page
1067
1068 return 0;
1069}
1070
Vijay Khemka63c99be2020-05-27 19:14:35 -07001071int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
1072 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001073{
1074 switch (frame)
1075 {
1076 case 1: // info_page
1077 return udbg_get_info_page(frame, page, next, count, buffer);
1078 case 2: // critical SEL
1079 return udbg_get_cri_sel(frame, page, next, count, buffer);
1080 case 3: // critical Sensor
1081 return udbg_get_cri_sensor(frame, page, next, count, buffer);
1082 default:
1083 return -1;
1084 }
1085}
1086
1087static uint8_t panel_main(uint8_t item)
1088{
1089 // Update item list when select item 0
1090 switch (item)
1091 {
1092 case 1:
1093 return panels[PANEL_BOOT_ORDER].select(0);
1094 case 2:
1095 return panels[PANEL_POWER_POLICY].select(0);
1096 default:
1097 return PANEL_MAIN;
1098 }
1099}
1100
Willy Tue39f9392022-06-15 13:24:20 -07001101static uint8_t panel_boot_order(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001102{
Willy Tue39f9392022-06-15 13:24:20 -07001103 /* To be implemented */
1104#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001105 int i;
1106 unsigned char buff[MAX_VALUE_LEN], pickup, len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301107 size_t pos = plat_get_fru_sel();
Willy Tue39f9392022-06-15 13:24:20 -07001108 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
1109 {
1110 if (item > 0 && item < SIZE_BOOT_ORDER)
1111 {
1112 pickup = buff[item];
1113 while (item > 1)
1114 {
1115 buff[item] = buff[item - 1];
1116 item--;
1117 }
1118 buff[item] = pickup;
1119 buff[0] |= 0x80;
1120 pal_set_boot_order(pos, buff, buff, &len);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001121
Willy Tue39f9392022-06-15 13:24:20 -07001122 // refresh items
1123 return panels[PANEL_BOOT_ORDER].select(0);
1124 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001125
Willy Tue39f9392022-06-15 13:24:20 -07001126 // '*': boot flags valid, BIOS has not yet read
1127 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32, "Boot Order%c",
1128 (buff[0] & 0x80) ? '*' : '\0');
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001129
Willy Tue39f9392022-06-15 13:24:20 -07001130 for (i = 1; i < SIZE_BOOT_ORDER; i++)
1131 {
1132 switch (buff[i])
1133 {
1134 case 0x0:
1135 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1136 " USB device");
1137 break;
1138 case 0x1:
1139 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1140 " Network v4");
1141 break;
1142 case (0x1 | 0x8):
1143 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1144 " Network v6");
1145 break;
1146 case 0x2:
1147 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1148 " SATA HDD");
1149 break;
1150 case 0x3:
1151 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1152 " SATA-CDROM");
1153 break;
1154 case 0x4:
1155 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1156 " Other");
1157 break;
1158 default:
1159 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
1160 break;
1161 }
1162 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001163
Willy Tue39f9392022-06-15 13:24:20 -07001164 // remove empty items
1165 for (i--;
1166 (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0);
1167 i--)
1168 ;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001169
Willy Tue39f9392022-06-15 13:24:20 -07001170 panels[PANEL_BOOT_ORDER].item_num = i;
1171 }
1172 else
1173 {
1174 panels[PANEL_BOOT_ORDER].item_num = 0;
1175 }
1176#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001177 return PANEL_BOOT_ORDER;
1178}
1179
Willy Tue39f9392022-06-15 13:24:20 -07001180static uint8_t panel_power_policy(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001181{
Willy Tue39f9392022-06-15 13:24:20 -07001182/* To be cleaned */
1183#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001184 uint8_t buff[32] = {0};
1185 uint8_t res_len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301186 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001187 uint8_t policy;
Willy Tue39f9392022-06-15 13:24:20 -07001188 uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1189 POWER_CFG_OFF};
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001190
Willy Tue39f9392022-06-15 13:24:20 -07001191 if (pos != FRU_ALL)
1192 {
1193 if (item > 0 && item <= sizeof(pwr_policy_item_map))
1194 {
1195 policy = pwr_policy_item_map[item - 1];
1196 pal_set_power_restore_policy(pos, &policy, NULL);
1197 }
1198 pal_get_chassis_status(pos, NULL, buff, &res_len);
1199 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1200 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32, "%cPower On",
1201 policy == POWER_CFG_ON ? '*' : ' ');
1202 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32, "%cLast State",
1203 policy == POWER_CFG_LPS ? '*' : ' ');
1204 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32, "%cPower Off",
1205 policy == POWER_CFG_OFF ? '*' : ' ');
1206 panels[PANEL_POWER_POLICY].item_num = 3;
1207 }
1208 else
1209 {
1210 panels[PANEL_POWER_POLICY].item_num = 0;
1211 }
1212#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001213 return PANEL_POWER_POLICY;
1214}
1215
1216int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001217 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001218{
1219 if (panel > panelNum || panel < PANEL_MAIN)
1220 return IPMI_CC_PARM_OUT_OF_RANGE;
1221
1222 // No more item; End of item list
1223 if (item > panels[panel].item_num)
1224 return IPMI_CC_PARM_OUT_OF_RANGE;
1225
1226 switch (operation)
1227 {
1228 case 0: // Get Description
1229 break;
1230 case 1: // Select item
1231 panel = panels[panel].select(item);
1232 item = 0;
1233 break;
1234 case 2: // Back
1235 panel = panels[panel].parent;
1236 item = 0;
1237 break;
1238 default:
1239 return IPMI_CC_PARM_OUT_OF_RANGE;
1240 }
1241
1242 buffer[0] = panel;
1243 buffer[1] = item;
1244 buffer[2] = strlen(panels[panel].item_str[item]);
1245 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1246 {
1247 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1248 }
1249 *count = buffer[2] + 3;
1250 return IPMI_CC_OK;
1251}
1252
1253} // end of namespace ipmi