blob: 3579ef19d8166a4fb74ad85552b00c2df98ee25f [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
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800135 for (ptr = lbuf; *ptr != '\0'; ptr++)
136 {
137 if (isFull())
138 {
139 if (overwrite)
140 {
141 if (buf[idx_head] == LINE_DELIMITER)
142 lines--;
143 idx_head = (idx_head + 1) % max_size;
144 }
145 else
146 return -1;
147 }
148
149 buf[idx_tail] = *ptr;
150 if (*ptr == LINE_DELIMITER)
151 lines++;
152
153 idx_tail = (idx_tail + 1) % max_size;
154 }
155
156 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
157
158 if (pages > max_page)
159 pages = max_page;
160
161 return 0;
162}
163
164// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700165int frame::insert(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800166{
167 const size_t buf_size = 128;
168 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700169 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800170 int ret;
171 int i;
172
173 ret = parse(lbuf, buf_size, string, indent);
174
175 if (ret < 0)
176 return ret;
177
178 for (i = strlen(lbuf) - 1; i >= 0; i--)
179 {
180 ptr = &lbuf[i];
181 if (isFull())
182 {
183 if (overwrite)
184 {
185 idx_tail = (idx_tail + max_size - 1) % max_size;
186 if (buf[idx_tail] == LINE_DELIMITER)
187 lines--;
188 }
189 else
190 return -1;
191 }
192
193 idx_head = (idx_head + max_size - 1) % max_size;
194
195 buf[idx_head] = *ptr;
196 if (*ptr == LINE_DELIMITER)
197 lines++;
198 }
199
200 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
201
202 if (pages > max_page)
203 pages = max_page;
204
205 return 0;
206}
207
208// return page size
Vijay Khemka63c99be2020-05-27 19:14:35 -0700209int frame::getPage(int page, char* page_buf, size_t page_buf_size)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800210{
211 int ret;
212 uint16_t line = 0;
213 uint16_t idx, len;
214
215 if (buf == NULL)
216 return -1;
217
218 // 1-based page
219 if (page > pages || page < 1)
220 return -1;
221
Willy Tue39f9392022-06-15 13:24:20 -0700222 if (page_buf == NULL || page_buf_size == 0)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800223 return -1;
224
225 ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages);
226 len = strlen(page_buf);
227 if (ret < 0)
228 return -1;
229
230 line = 0;
231 idx = idx_head;
232 while (line < ((page - 1) * line_per_page) && idx != idx_tail)
233 {
234 if (buf[idx] == LINE_DELIMITER)
235 line++;
236 idx = (idx + 1) % max_size;
237 }
238
239 while (line < ((page)*line_per_page) && idx != idx_tail)
240 {
241 if (buf[idx] == LINE_DELIMITER)
242 {
243 line++;
244 }
245 else
246 {
247 page_buf[len++] = buf[idx];
248 if (len == (page_buf_size - 1))
249 {
250 break;
251 }
252 }
253 idx = (idx + 1) % max_size;
254 }
255
256 return len;
257}
258
259// return 1 for frame buffer full
260int frame::isFull()
261{
262 if (buf == NULL)
263 return -1;
264
265 if ((idx_tail + 1) % max_size == idx_head)
266 return 1;
267 else
268 return 0;
269}
270
271// return 1 for Escape Sequence
272int frame::isEscSeq(char chr)
273{
274 uint8_t curr_sts = esc_sts;
275
276 if (esc_sts == 0 && (chr == 0x1b))
277 esc_sts = 1; // Escape Sequence
278 else if (esc_sts == 1 && (chr == 0x5b))
279 esc_sts = 2; // Control Sequence Introducer(CSI)
280 else if (esc_sts == 1 && (chr != 0x5b))
281 esc_sts = 0;
282 else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e))
283 esc_sts = 0;
284
285 if (curr_sts || esc_sts)
286 return 1;
287 else
288 return 0;
289}
290
291// return 0 on success
Vijay Khemka63c99be2020-05-27 19:14:35 -0700292int frame::parse(char* lbuf, size_t buf_size, const char* input, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800293{
294 uint8_t pos, esc;
Willy Tue39f9392022-06-15 13:24:20 -0700295 size_t i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800296 const char *in, *end;
297
298 if (buf == NULL || input == NULL)
299 return -1;
300
301 if (indent >= line_width || indent < 0)
302 return -1;
303
304 in = input;
305 end = in + strlen(input);
306 pos = 0; // line position
307 esc = 0; // escape state
308 i = 0; // buf index
309 while (in != end)
310 {
311 if (i >= buf_size)
312 break;
313
314 if (pos < indent)
315 {
316 // fill indent
317 lbuf[i++] = ' ';
318 pos++;
319 continue;
320 }
321
322 esc = isEscSeq(*in);
323
324 if (!esc && pos == line_width)
325 {
326 lbuf[i++] = LINE_DELIMITER;
327 pos = 0;
328 continue;
329 }
330
331 if (!esc)
332 pos++;
333
334 // fill input data
335 lbuf[i++] = *(in++);
336 }
337
338 // padding
339 while (pos <= line_width)
340 {
341 if (i >= buf_size)
342 break;
343 if (pos < line_width)
344 lbuf[i++] = ' ';
345 else
346 lbuf[i++] = LINE_DELIMITER;
347 pos++;
348 }
349
350 // full
351 if (i >= buf_size)
352 return -1;
353
354 lbuf[i++] = '\0';
355
356 return 0;
357}
358
Vijay Khemka63c99be2020-05-27 19:14:35 -0700359static int chk_cri_sel_update(uint8_t* cri_sel_up)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800360{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700361 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800362 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530363 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800364 static uint8_t pre_pos = 0xff;
365
366 fp = fopen("/mnt/data/cri_sel", "r");
367 if (fp)
368 {
369 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
370 (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos))
371 {
372 *cri_sel_up = 1;
373 }
374 else
375 {
376 *cri_sel_up = 0;
377 }
378 fclose(fp);
379 }
380 else
381 {
382 if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos)
383 {
384 *cri_sel_up = 1;
385 }
386 else
387 {
388 *cri_sel_up = 0;
389 }
390 }
391 pre_pos = pos;
392 return 0;
393}
394
Vijay Khemka63c99be2020-05-27 19:14:35 -0700395int plat_udbg_get_frame_info(uint8_t* num)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800396{
397 *num = 3;
398 return 0;
399}
400
Vijay Khemka63c99be2020-05-27 19:14:35 -0700401int plat_udbg_get_updated_frames(uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800402{
403 uint8_t cri_sel_up = 0;
404 uint8_t info_page_up = 1;
405
406 *count = 0;
407
408 // info page update
409 if (info_page_up == 1)
410 {
411 buffer[*count] = 1;
412 *count += 1;
413 }
414
415 // cri sel update
416 chk_cri_sel_update(&cri_sel_up);
417 if (cri_sel_up == 1)
418 {
419 buffer[*count] = 2;
420 *count += 1;
421 }
422
423 // cri sensor update
424 buffer[*count] = 3;
425 *count += 1;
426
427 return 0;
428}
429
Vijay Khemka63c99be2020-05-27 19:14:35 -0700430int plat_udbg_get_post_desc(uint8_t index, uint8_t* next, uint8_t phase,
431 uint8_t* end, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800432{
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700433 nlohmann::json postObj;
434 std::string postCode;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800435
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700436 /* Get post description data stored in json file */
437 std::ifstream file(JSON_POST_DATA_FILE);
438 if (file)
439 {
440 file >> postObj;
441 file.close();
442 }
443 else
444 {
445 phosphor::logging::log<phosphor::logging::level::ERR>(
446 "Post code description file not found",
447 phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE));
448 return -1;
449 }
450
451 std::string phaseStr = "PhaseAny";
452 if (postObj.find(phaseStr) == postObj.end())
453 {
454 phaseStr = "Phase" + std::to_string(phase);
455 }
456
457 if (postObj.find(phaseStr) == postObj.end())
458 {
459 phosphor::logging::log<phosphor::logging::level::ERR>(
460 "Post code phase not available",
461 phosphor::logging::entry("PHASE=%d", phase));
462 return -1;
463 }
464
465 auto phaseObj = postObj[phaseStr];
466 int phaseSize = phaseObj.size();
467
468 for (int i = 0; i < phaseSize; i++)
469 {
470 postCode = phaseObj[i][0];
471 if (index == stoul(postCode, nullptr, 16))
472 {
473 std::string postDesc = phaseObj[i][1];
474 *length = postDesc.size();
475 memcpy(buffer, postDesc.data(), *length);
476 buffer[*length] = '\0';
477
478 if (phaseSize != i + 1)
479 {
480 postCode = phaseObj[i + 1][0];
481 *next = stoul(postCode, nullptr, 16);
482 *end = 0;
483 }
484 else
485 {
486 if (postObj.size() != phase)
487 {
488 std::string nextPhaseStr =
489 "Phase" + std::to_string(phase + 1);
490 postCode = postObj[nextPhaseStr][0][0];
491 *next = stoul(postCode, nullptr, 16);
492 *end = 0;
493 }
494 else
495 {
496 *next = 0xff;
497 *end = 1;
498 }
499 }
500
501 return 0;
502 }
503 }
504
505 phosphor::logging::log<phosphor::logging::level::ERR>(
506 "Post code description data not available",
507 phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index));
508 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800509}
510
Vijay Khemka63c99be2020-05-27 19:14:35 -0700511int plat_udbg_get_gpio_desc(uint8_t index, uint8_t* next, uint8_t* level,
512 uint8_t* def, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800513{
Vijay Khemka38183d62019-08-28 16:19:33 -0700514 nlohmann::json gpioObj;
515 std::string gpioPin;
516
517 /* Get gpio data stored in json file */
518 std::ifstream file(JSON_GPIO_DATA_FILE);
519 if (file)
520 {
521 file >> gpioObj;
522 file.close();
523 }
524 else
525 {
526 phosphor::logging::log<phosphor::logging::level::ERR>(
527 "GPIO pin description file not found",
528 phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s",
529 JSON_GPIO_DATA_FILE));
530 return -1;
531 }
532
533 if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end())
534 {
535 phosphor::logging::log<phosphor::logging::level::ERR>(
536 "GPIO pin details not available",
537 phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY));
538 return -1;
539 }
540
541 auto obj = gpioObj[DEBUG_GPIO_KEY];
542 int objSize = obj.size();
543
544 for (int i = 0; i < objSize; i++)
545 {
546 if (obj[i].size() != GPIO_ARRAY_SIZE)
547 {
548 phosphor::logging::log<phosphor::logging::level::ERR>(
549 "Size of gpio array is incorrect",
550 phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE));
551 return -1;
552 }
553
554 gpioPin = obj[i][GPIO_PIN_INDEX];
555 if (index == stoul(gpioPin, nullptr, 16))
556 {
557 if (objSize != i + 1)
558 {
559 gpioPin = obj[i + 1][GPIO_PIN_INDEX];
560 *next = stoul(gpioPin, nullptr, 16);
561 }
562 else
563 {
564 *next = 0xff;
565 }
566
567 *level = obj[i][GPIO_LEVEL_INDEX];
568 *def = obj[i][GPIO_DEF_INDEX];
569 std::string gpioDesc = obj[i][GPIO_DESC_INDEX];
570 *length = gpioDesc.size();
571 memcpy(buffer, gpioDesc.data(), *length);
572 buffer[*length] = '\0';
573
574 return 0;
575 }
576 }
577
578 phosphor::logging::log<phosphor::logging::level::ERR>(
579 "GPIO pin description data not available",
580 phosphor::logging::entry("GPIO_PIN=0x%x", index));
581 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800582}
583
Willy Tue39f9392022-06-15 13:24:20 -0700584static int udbg_get_cri_sel(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700585 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800586{
587 int len;
588 int ret;
Willy Tue39f9392022-06-15 13:24:20 -0700589 char line_buff[FRAME_PAGE_BUF_SIZE];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700590 const char* ptr;
591 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800592 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530593 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800594 static uint8_t pre_pos = FRU_ALL;
595 bool pos_changed = pre_pos != pos;
596
597 pre_pos = pos;
598
599 /* Revisit this */
600 fp = fopen("/mnt/data/cri_sel", "r");
601 if (fp)
602 {
603 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
604 (file_stat.st_mtime != frame_sel.mtime || pos_changed))
605 {
606 // initialize and clear frame
607 frame_sel.init(FRAME_BUFF_SIZE);
608 frame_sel.overwrite = 1;
609 frame_sel.max_page = 20;
610 frame_sel.mtime = file_stat.st_mtime;
611 snprintf(frame_sel.title, 32, "Cri SEL");
612
613 while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp))
614 {
615 // Remove newline
616 line_buff[strlen(line_buff) - 1] = '\0';
617 ptr = line_buff;
618 // Find message
619 ptr = strstr(ptr, "local0.err");
620 if (ptr == NULL)
621 {
622 continue;
623 }
624
625 if ((ptr = strrchr(ptr, ':')) == NULL)
626 {
627 continue;
628 }
629 len = strlen(ptr);
630 if (len > 2)
631 {
632 // to skip log string ": "
633 ptr += 2;
634 }
635 // Write new message
636 frame_sel.insert(ptr, 0);
637 }
638 }
639 fclose(fp);
640 }
641 else
642 {
643 // Title only
644 frame_sel.init(FRAME_BUFF_SIZE);
645 snprintf(frame_sel.title, 32, "Cri SEL");
646 frame_sel.mtime = 0;
647 }
648
649 if (page > frame_sel.pages)
650 {
651 return -1;
652 }
653
Vijay Khemka63c99be2020-05-27 19:14:35 -0700654 ret = frame_sel.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800655 if (ret < 0)
656 {
657 *count = 0;
658 return -1;
659 }
660 *count = (uint8_t)ret;
661
662 if (page < frame_sel.pages)
663 *next = page + 1;
664 else
665 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
666 // last page
667
668 return 0;
669}
670
Willy Tue39f9392022-06-15 13:24:20 -0700671static int udbg_get_cri_sensor(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700672 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800673{
Vijay Khemka427b2762019-12-12 12:49:25 -0800674 int ret;
675 double fvalue;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530676 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800677
678 if (page == 1)
679 {
680 // Only update frame data while getting page 1
681
682 // initialize and clear frame
683 frame_snr.init(FRAME_BUFF_SIZE);
684 snprintf(frame_snr.title, 32, "CriSensor");
Vijay Khemka427b2762019-12-12 12:49:25 -0800685
686 nlohmann::json senObj;
687
688 /* Get critical sensor names stored in json file */
689 std::ifstream file(JSON_SENSOR_NAMES_FILE);
690 if (file)
691 {
692 file >> senObj;
693 file.close();
694 }
695 else
696 {
697 phosphor::logging::log<phosphor::logging::level::ERR>(
698 "Critical Sensor names file not found",
699 phosphor::logging::entry("CRI_SENSOR_NAMES_FILE=%s",
700 JSON_SENSOR_NAMES_FILE));
701 return -1;
702 }
703
704 /* Get sensors values for all critical sensors */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700705 for (auto& j : senObj.items())
Vijay Khemka427b2762019-12-12 12:49:25 -0800706 {
707 std::string senName = j.key();
708 auto val = j.value();
709
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530710 if (senName[0] == '_')
711 {
712 senName = std::to_string(pos) + senName;
713 }
714
Vijay Khemka427b2762019-12-12 12:49:25 -0800715 if (ipmi::storage::getSensorValue(senName, fvalue) == 0)
716 {
717 std::stringstream ss;
Vijay Khemkaf43fad42019-12-26 11:47:58 -0800718 int prec = 0; // Default value
719
720 if (val.find("precision") != val.end())
721 prec = val["precision"];
722
723 ss << std::fixed << std::setprecision(prec) << fvalue;
Vijay Khemka427b2762019-12-12 12:49:25 -0800724
725 std::string senStr;
726 if (val.find("short_name") != val.end())
727 senStr = val["short_name"];
728 else
729 senStr = senName;
730
731 senStr += ss.str();
Vijay Khemka58bd5d82019-12-13 11:05:56 -0800732
733 /* Get unit string for sensor and append in output */
734 std::string unitStr;
735 if (ipmi::storage::getSensorUnit(senName, unitStr) == 0)
736 senStr += unitStr;
737
Vijay Khemka427b2762019-12-12 12:49:25 -0800738 frame_snr.append(senStr.c_str(), 0);
739 }
740 else
741 {
742 phosphor::logging::log<phosphor::logging::level::INFO>(
743 "Critical sensor not found",
744 phosphor::logging::entry("CRI_SENSOR_NAME=%s",
745 senName.c_str()));
746 }
747 }
748
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800749 } // End of update frame
750
751 if (page > frame_snr.pages)
752 {
753 return -1;
754 }
755
Vijay Khemka63c99be2020-05-27 19:14:35 -0700756 ret = frame_snr.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800757 if (ret < 0)
758 {
759 *count = 0;
760 return -1;
761 }
762 *count = (uint8_t)ret;
763
764 if (page < frame_snr.pages)
765 *next = page + 1;
766 else
767 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
768 // last page
769
770 return 0;
771}
772
Vijay Khemka63c99be2020-05-27 19:14:35 -0700773static int getBiosVer(std::string& ver)
Vijay Khemka88884b82019-08-27 15:23:07 -0700774{
775 nlohmann::json appObj;
776
777 std::ifstream file(JSON_APP_DATA_FILE);
778 if (file)
779 {
780 file >> appObj;
781 file.close();
782 if (appObj.find(KEY_SYSFW_VER) != appObj.end())
783 {
784 ver = appObj[KEY_SYSFW_VER].get<std::string>();
785 return 0;
786 }
787 }
788
789 return -1;
790}
791
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530792int sendBicCmd(uint8_t netFn, uint8_t cmd, uint8_t bicAddr,
793 std::vector<uint8_t>& cmdData, std::vector<uint8_t>& respData)
794{
795 static constexpr uint8_t lun = 0;
796
797 auto bus = getSdBus();
798
799 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
800 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
801 "org.openbmc.Ipmb", "sendRequest");
802 method.append(bicAddr, netFn, lun, cmd, cmdData);
803
804 auto reply = bus->call(method);
805 if (reply.is_method_error())
806 {
807 phosphor::logging::log<phosphor::logging::level::ERR>(
808 "Error reading from BIC");
809 return -1;
810 }
811
812 IpmbMethodType resp;
813 reply.read(resp);
814
815 respData =
816 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
817
818 return 0;
819}
820
Vijay Khemka63c99be2020-05-27 19:14:35 -0700821int sendMeCmd(uint8_t netFn, uint8_t cmd, std::vector<uint8_t>& cmdData,
822 std::vector<uint8_t>& respData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -0700823{
824 auto bus = getSdBus();
825
826 if (DEBUG)
827 {
828 std::cout << "ME NetFn:cmd " << (int)netFn << ":" << (int)cmd << "\n";
829 std::cout << "ME req data: ";
830 for (auto d : cmdData)
831 {
832 std::cout << d << " ";
833 }
834 std::cout << "\n";
835 }
836
837 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
838 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
839 "org.openbmc.Ipmb", "sendRequest");
840 method.append(meAddress, netFn, lun, cmd, cmdData);
841
842 auto reply = bus->call(method);
843 if (reply.is_method_error())
844 {
845 phosphor::logging::log<phosphor::logging::level::ERR>(
846 "Error reading from ME");
847 return -1;
848 }
849
850 IpmbMethodType resp;
851 reply.read(resp);
852
853 respData =
854 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
855
856 if (DEBUG)
857 {
858 std::cout << "ME resp data: ";
859 for (auto d : respData)
860 {
861 std::cout << d << " ";
862 }
863 std::cout << "\n";
864 }
865
866 return 0;
867}
868
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530869static int getMeStatus(std::string& status, size_t pos)
Vijay Khemka317999d2020-01-02 13:43:42 -0800870{
871 uint8_t cmd = 0x01; // Get Device id command
872 uint8_t netFn = 0x06; // Netfn for APP
873 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
874 std::vector<uint8_t> cmdData;
875
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530876 uint8_t meAddr = meAddress;
877 bool platform = isMultiHostPlatform();
878 if (platform == true)
879 {
880 meAddr = ((pos - 1) << 2);
881 }
882
Vijay Khemka317999d2020-01-02 13:43:42 -0800883 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
884 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
885 "org.openbmc.Ipmb", "sendRequest");
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530886 method.append(meAddr, netFn, lun, cmd, cmdData);
Vijay Khemka317999d2020-01-02 13:43:42 -0800887
888 auto reply = bus->call(method);
889 if (reply.is_method_error())
890 {
891 std::cerr << "Error reading from ME\n";
892 return -1;
893 }
894
895 IpmbMethodType resp;
896 reply.read(resp);
897
898 std::vector<uint8_t> data;
899 data = std::get<5>(resp);
900
901 if (DEBUG)
902 {
903 std::cout << "ME Get ID: ";
904 for (size_t d : data)
905 {
906 std::cout << d << " ";
907 }
908 std::cout << "\n";
909 }
910
911 if (data[2] & 0x80)
912 status = "recovery mode";
913 else
914 status = "operation mode";
915
916 return 0;
917}
918
Willy Tue39f9392022-06-15 13:24:20 -0700919static int udbg_get_info_page(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700920 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800921{
Willy Tue39f9392022-06-15 13:24:20 -0700922 char line_buff[1000];
923 [[maybe_unused]] char* pres_dev = line_buff;
924 [[maybe_unused]] size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800925 int ret;
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530926 std::string serialName = "SerialNumber";
927 std::string partName = "PartNumber";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800928 std::string verDel = "VERSION=";
929 std::string verPath = "/etc/os-release";
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530930 size_t hostPosition;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800931
932 if (page == 1)
933 {
934 // Only update frame data while getting page 1
935
936 // initialize and clear frame
937 frame_info.init(FRAME_BUFF_SIZE);
938 snprintf(frame_info.title, 32, "SYS_Info");
939
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530940 bool platform = isMultiHostPlatform();
941 if (platform == true)
942 {
943 hostPosition = getSelectorPosition();
944 }
945
946 if (hostPosition == BMC_POSITION || INSTANCES == "0")
947 {
948 frame_info.append("FRU:spb", 0);
949 }
950 else if (hostPosition != BMC_POSITION && hostPosition <= MAX_HOST_POS)
951 {
952 std::string data = "FRU:slot" + std::to_string(hostPosition);
953 frame_info.append(data.c_str(), 0);
954 }
955
956 // FRU
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800957 std::string data;
958 frame_info.append("SN:", 0);
959 if (getFruData(data, serialName) != 0)
960 {
961 data = "Not Found";
962 }
963 frame_info.append(data.c_str(), 1);
964 frame_info.append("PN:", 0);
965 if (getFruData(data, partName) != 0)
966 {
967 data = "Not Found";
968 }
969 frame_info.append(data.c_str(), 1);
970
971 // LAN
972 getNetworkData(3, line_buff);
973 frame_info.append("BMC_IP:", 0);
974 frame_info.append(line_buff, 1);
975 getNetworkData(59, line_buff);
976 frame_info.append("BMC_IPv6:", 0);
977 frame_info.append(line_buff, 1);
978
979 // BMC ver
980 std::ifstream file(verPath);
981 if (file)
982 {
983 std::string line;
984 while (std::getline(file, line))
985 {
986 if (line.find(verDel) != std::string::npos)
987 {
988 std::string bmcVer = line.substr(verDel.size());
989 frame_info.append("BMC_FW_ver:", 0);
990 frame_info.append(bmcVer.c_str(), 1);
991 break;
992 }
993 }
994 }
995
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530996 if (hostPosition != BMC_POSITION)
Vijay Khemka88884b82019-08-27 15:23:07 -0700997 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530998 // BIOS ver
999 std::string biosVer;
1000 if (getBiosVer(biosVer) == 0)
1001 {
1002 frame_info.append("BIOS_FW_ver:", 0);
1003 frame_info.append(biosVer.c_str(), 1);
1004 }
1005 // ME status
1006 std::string meStatus;
1007 if (getMeStatus(meStatus, pos) != 0)
1008 {
1009 phosphor::logging::log<phosphor::logging::level::WARNING>(
1010 "Reading ME status failed");
1011 meStatus = "unknown";
1012 }
1013 frame_info.append("ME_status:", 0);
1014 frame_info.append(meStatus.c_str(), 1);
Vijay Khemka88884b82019-08-27 15:23:07 -07001015 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001016
Vijay Khemka317999d2020-01-02 13:43:42 -08001017 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001018 // Board ID
1019
1020 // Battery - Use Escape sequence
1021 frame_info.append("Battery:", 0);
1022 frame_info.append(ESC_BAT " ", 1);
1023 // frame_info.append(&frame_info, esc_bat, 1);
1024
1025 // MCU Version - Use Escape sequence
1026 frame_info.append("MCUbl_ver:", 0);
1027 frame_info.append(ESC_MCU_BL_VER, 1);
1028 frame_info.append("MCU_ver:", 0);
1029 frame_info.append(ESC_MCU_RUN_VER, 1);
1030
1031 // TBD:
1032 // Sys config present device
1033
1034 } // End of update frame
1035
1036 if (page > frame_info.pages)
1037 {
1038 return -1;
1039 }
1040
Vijay Khemka63c99be2020-05-27 19:14:35 -07001041 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001042 if (ret < 0)
1043 {
1044 *count = 0;
1045 return -1;
1046 }
1047 *count = (uint8_t)ret;
1048
1049 if (page < frame_info.pages)
1050 *next = page + 1;
1051 else
1052 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
1053 // last page
1054
1055 return 0;
1056}
1057
Vijay Khemka63c99be2020-05-27 19:14:35 -07001058int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
1059 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001060{
1061 switch (frame)
1062 {
1063 case 1: // info_page
1064 return udbg_get_info_page(frame, page, next, count, buffer);
1065 case 2: // critical SEL
1066 return udbg_get_cri_sel(frame, page, next, count, buffer);
1067 case 3: // critical Sensor
1068 return udbg_get_cri_sensor(frame, page, next, count, buffer);
1069 default:
1070 return -1;
1071 }
1072}
1073
1074static uint8_t panel_main(uint8_t item)
1075{
1076 // Update item list when select item 0
1077 switch (item)
1078 {
1079 case 1:
1080 return panels[PANEL_BOOT_ORDER].select(0);
1081 case 2:
1082 return panels[PANEL_POWER_POLICY].select(0);
1083 default:
1084 return PANEL_MAIN;
1085 }
1086}
1087
Willy Tue39f9392022-06-15 13:24:20 -07001088static uint8_t panel_boot_order(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001089{
Willy Tue39f9392022-06-15 13:24:20 -07001090 /* To be implemented */
1091#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001092 int i;
1093 unsigned char buff[MAX_VALUE_LEN], pickup, len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301094 size_t pos = plat_get_fru_sel();
Willy Tue39f9392022-06-15 13:24:20 -07001095 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
1096 {
1097 if (item > 0 && item < SIZE_BOOT_ORDER)
1098 {
1099 pickup = buff[item];
1100 while (item > 1)
1101 {
1102 buff[item] = buff[item - 1];
1103 item--;
1104 }
1105 buff[item] = pickup;
1106 buff[0] |= 0x80;
1107 pal_set_boot_order(pos, buff, buff, &len);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001108
Willy Tue39f9392022-06-15 13:24:20 -07001109 // refresh items
1110 return panels[PANEL_BOOT_ORDER].select(0);
1111 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001112
Willy Tue39f9392022-06-15 13:24:20 -07001113 // '*': boot flags valid, BIOS has not yet read
1114 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32, "Boot Order%c",
1115 (buff[0] & 0x80) ? '*' : '\0');
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001116
Willy Tue39f9392022-06-15 13:24:20 -07001117 for (i = 1; i < SIZE_BOOT_ORDER; i++)
1118 {
1119 switch (buff[i])
1120 {
1121 case 0x0:
1122 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1123 " USB device");
1124 break;
1125 case 0x1:
1126 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1127 " Network v4");
1128 break;
1129 case (0x1 | 0x8):
1130 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1131 " Network v6");
1132 break;
1133 case 0x2:
1134 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1135 " SATA HDD");
1136 break;
1137 case 0x3:
1138 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1139 " SATA-CDROM");
1140 break;
1141 case 0x4:
1142 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1143 " Other");
1144 break;
1145 default:
1146 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
1147 break;
1148 }
1149 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001150
Willy Tue39f9392022-06-15 13:24:20 -07001151 // remove empty items
1152 for (i--;
1153 (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0);
1154 i--)
1155 ;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001156
Willy Tue39f9392022-06-15 13:24:20 -07001157 panels[PANEL_BOOT_ORDER].item_num = i;
1158 }
1159 else
1160 {
1161 panels[PANEL_BOOT_ORDER].item_num = 0;
1162 }
1163#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001164 return PANEL_BOOT_ORDER;
1165}
1166
Willy Tue39f9392022-06-15 13:24:20 -07001167static uint8_t panel_power_policy(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001168{
Willy Tue39f9392022-06-15 13:24:20 -07001169/* To be cleaned */
1170#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001171 uint8_t buff[32] = {0};
1172 uint8_t res_len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301173 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001174 uint8_t policy;
Willy Tue39f9392022-06-15 13:24:20 -07001175 uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1176 POWER_CFG_OFF};
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001177
Willy Tue39f9392022-06-15 13:24:20 -07001178 if (pos != FRU_ALL)
1179 {
1180 if (item > 0 && item <= sizeof(pwr_policy_item_map))
1181 {
1182 policy = pwr_policy_item_map[item - 1];
1183 pal_set_power_restore_policy(pos, &policy, NULL);
1184 }
1185 pal_get_chassis_status(pos, NULL, buff, &res_len);
1186 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1187 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32, "%cPower On",
1188 policy == POWER_CFG_ON ? '*' : ' ');
1189 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32, "%cLast State",
1190 policy == POWER_CFG_LPS ? '*' : ' ');
1191 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32, "%cPower Off",
1192 policy == POWER_CFG_OFF ? '*' : ' ');
1193 panels[PANEL_POWER_POLICY].item_num = 3;
1194 }
1195 else
1196 {
1197 panels[PANEL_POWER_POLICY].item_num = 0;
1198 }
1199#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001200 return PANEL_POWER_POLICY;
1201}
1202
1203int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001204 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001205{
1206 if (panel > panelNum || panel < PANEL_MAIN)
1207 return IPMI_CC_PARM_OUT_OF_RANGE;
1208
1209 // No more item; End of item list
1210 if (item > panels[panel].item_num)
1211 return IPMI_CC_PARM_OUT_OF_RANGE;
1212
1213 switch (operation)
1214 {
1215 case 0: // Get Description
1216 break;
1217 case 1: // Select item
1218 panel = panels[panel].select(item);
1219 item = 0;
1220 break;
1221 case 2: // Back
1222 panel = panels[panel].parent;
1223 item = 0;
1224 break;
1225 default:
1226 return IPMI_CC_PARM_OUT_OF_RANGE;
1227 }
1228
1229 buffer[0] = panel;
1230 buffer[1] = item;
1231 buffer[2] = strlen(panels[panel].item_str[item]);
1232 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1233 {
1234 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1235 }
1236 *count = buffer[2] + 3;
1237 return IPMI_CC_OK;
1238}
1239
1240} // end of namespace ipmi