blob: c030e4e226447033150dde827672af4aa59cf2f2 [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
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053046size_t getSelectorPosition()
47{
48 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
49 std::string service =
50 getService(*dbus, ipmi::selector::interface, ipmi::selector::path);
51 Value variant = getDbusProperty(*dbus, service, ipmi::selector::path,
52 ipmi::selector::interface,
53 ipmi::selector::propertyName);
54 size_t result = std::get<size_t>(variant);
55 return result;
56}
57
Vijay Khemkae7d23d02019-03-08 13:13:40 -080058static int panelNum = (sizeof(panels) / sizeof(struct ctrl_panel)) - 1;
59
60/* Returns the FRU the hand-switch is switched to. If it is switched to BMC
61 * it returns FRU_ALL. Note, if in err, it returns FRU_ALL */
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053062static size_t plat_get_fru_sel()
Vijay Khemkae7d23d02019-03-08 13:13:40 -080063{
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053064 size_t position;
65 bool platform = isMultiHostPlatform();
66
67 if (platform == true)
68 {
69 try
70 {
71 size_t hostPosition = getSelectorPosition();
72 position = hostPosition;
73 if (position == BMC_POSITION)
74 {
75 return FRU_ALL;
76 }
77 }
78 catch (...)
79 {
80 std::cout << "Error reading host selector position" << std::endl;
81 }
82 }
83 else
84 {
85 // For Tiogapass it just return 1, can modify to support more platform
86 position = 1;
87 }
88 return position;
Vijay Khemkae7d23d02019-03-08 13:13:40 -080089}
90
91// return 0 on seccuess
92int frame::init(size_t size)
93{
94 // Reset status
95 idx_head = idx_tail = 0;
96 lines = 0;
97 esc_sts = 0;
98 pages = 1;
99
100 if (buf != NULL && max_size == size)
101 {
102 // reinit
103 return 0;
104 }
105
106 if (buf != NULL && max_size != size)
107 {
108 delete[] buf;
109 }
110 // Initialize Configuration
111 title[0] = '\0';
112 buf = new char[size];
113 max_size = size;
114 max_page = size;
115 line_per_page = 7;
116 line_width = 16;
117 overwrite = 0;
118
119 if (buf)
120 return 0;
121 else
122 return -1;
123}
124
125// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700126int frame::append(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800127{
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530128 const size_t buf_size = 128;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800129 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700130 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800131 int ret;
132
133 ret = parse(lbuf, buf_size, string, indent);
134
135 if (ret < 0)
136 return ret;
137
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800138 for (ptr = lbuf; *ptr != '\0'; ptr++)
139 {
140 if (isFull())
141 {
142 if (overwrite)
143 {
144 if (buf[idx_head] == LINE_DELIMITER)
145 lines--;
146 idx_head = (idx_head + 1) % max_size;
147 }
148 else
149 return -1;
150 }
151
152 buf[idx_tail] = *ptr;
153 if (*ptr == LINE_DELIMITER)
154 lines++;
155
156 idx_tail = (idx_tail + 1) % max_size;
157 }
158
159 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
160
161 if (pages > max_page)
162 pages = max_page;
163
164 return 0;
165}
166
167// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700168int frame::insert(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800169{
170 const size_t buf_size = 128;
171 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700172 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800173 int ret;
174 int i;
175
176 ret = parse(lbuf, buf_size, string, indent);
177
178 if (ret < 0)
179 return ret;
180
181 for (i = strlen(lbuf) - 1; i >= 0; i--)
182 {
183 ptr = &lbuf[i];
184 if (isFull())
185 {
186 if (overwrite)
187 {
188 idx_tail = (idx_tail + max_size - 1) % max_size;
189 if (buf[idx_tail] == LINE_DELIMITER)
190 lines--;
191 }
192 else
193 return -1;
194 }
195
196 idx_head = (idx_head + max_size - 1) % max_size;
197
198 buf[idx_head] = *ptr;
199 if (*ptr == LINE_DELIMITER)
200 lines++;
201 }
202
203 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
204
205 if (pages > max_page)
206 pages = max_page;
207
208 return 0;
209}
210
211// return page size
Vijay Khemka63c99be2020-05-27 19:14:35 -0700212int frame::getPage(int page, char* page_buf, size_t page_buf_size)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800213{
214 int ret;
215 uint16_t line = 0;
216 uint16_t idx, len;
217
218 if (buf == NULL)
219 return -1;
220
221 // 1-based page
222 if (page > pages || page < 1)
223 return -1;
224
Willy Tue39f9392022-06-15 13:24:20 -0700225 if (page_buf == NULL || page_buf_size == 0)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800226 return -1;
227
228 ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages);
229 len = strlen(page_buf);
230 if (ret < 0)
231 return -1;
232
233 line = 0;
234 idx = idx_head;
235 while (line < ((page - 1) * line_per_page) && idx != idx_tail)
236 {
237 if (buf[idx] == LINE_DELIMITER)
238 line++;
239 idx = (idx + 1) % max_size;
240 }
241
242 while (line < ((page)*line_per_page) && idx != idx_tail)
243 {
244 if (buf[idx] == LINE_DELIMITER)
245 {
246 line++;
247 }
248 else
249 {
250 page_buf[len++] = buf[idx];
251 if (len == (page_buf_size - 1))
252 {
253 break;
254 }
255 }
256 idx = (idx + 1) % max_size;
257 }
258
259 return len;
260}
261
262// return 1 for frame buffer full
263int frame::isFull()
264{
265 if (buf == NULL)
266 return -1;
267
268 if ((idx_tail + 1) % max_size == idx_head)
269 return 1;
270 else
271 return 0;
272}
273
274// return 1 for Escape Sequence
275int frame::isEscSeq(char chr)
276{
277 uint8_t curr_sts = esc_sts;
278
279 if (esc_sts == 0 && (chr == 0x1b))
280 esc_sts = 1; // Escape Sequence
281 else if (esc_sts == 1 && (chr == 0x5b))
282 esc_sts = 2; // Control Sequence Introducer(CSI)
283 else if (esc_sts == 1 && (chr != 0x5b))
284 esc_sts = 0;
285 else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e))
286 esc_sts = 0;
287
288 if (curr_sts || esc_sts)
289 return 1;
290 else
291 return 0;
292}
293
294// return 0 on success
Vijay Khemka63c99be2020-05-27 19:14:35 -0700295int frame::parse(char* lbuf, size_t buf_size, const char* input, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800296{
297 uint8_t pos, esc;
Willy Tue39f9392022-06-15 13:24:20 -0700298 size_t i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800299 const char *in, *end;
300
301 if (buf == NULL || input == NULL)
302 return -1;
303
304 if (indent >= line_width || indent < 0)
305 return -1;
306
307 in = input;
308 end = in + strlen(input);
309 pos = 0; // line position
310 esc = 0; // escape state
311 i = 0; // buf index
312 while (in != end)
313 {
314 if (i >= buf_size)
315 break;
316
317 if (pos < indent)
318 {
319 // fill indent
320 lbuf[i++] = ' ';
321 pos++;
322 continue;
323 }
324
325 esc = isEscSeq(*in);
326
327 if (!esc && pos == line_width)
328 {
329 lbuf[i++] = LINE_DELIMITER;
330 pos = 0;
331 continue;
332 }
333
334 if (!esc)
335 pos++;
336
337 // fill input data
338 lbuf[i++] = *(in++);
339 }
340
341 // padding
342 while (pos <= line_width)
343 {
344 if (i >= buf_size)
345 break;
346 if (pos < line_width)
347 lbuf[i++] = ' ';
348 else
349 lbuf[i++] = LINE_DELIMITER;
350 pos++;
351 }
352
353 // full
354 if (i >= buf_size)
355 return -1;
356
357 lbuf[i++] = '\0';
358
359 return 0;
360}
361
Vijay Khemka63c99be2020-05-27 19:14:35 -0700362static int chk_cri_sel_update(uint8_t* cri_sel_up)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800363{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700364 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800365 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530366 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800367 static uint8_t pre_pos = 0xff;
368
369 fp = fopen("/mnt/data/cri_sel", "r");
370 if (fp)
371 {
372 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
373 (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos))
374 {
375 *cri_sel_up = 1;
376 }
377 else
378 {
379 *cri_sel_up = 0;
380 }
381 fclose(fp);
382 }
383 else
384 {
385 if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos)
386 {
387 *cri_sel_up = 1;
388 }
389 else
390 {
391 *cri_sel_up = 0;
392 }
393 }
394 pre_pos = pos;
395 return 0;
396}
397
Vijay Khemka63c99be2020-05-27 19:14:35 -0700398int plat_udbg_get_frame_info(uint8_t* num)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800399{
400 *num = 3;
401 return 0;
402}
403
Vijay Khemka63c99be2020-05-27 19:14:35 -0700404int plat_udbg_get_updated_frames(uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800405{
406 uint8_t cri_sel_up = 0;
407 uint8_t info_page_up = 1;
408
409 *count = 0;
410
411 // info page update
412 if (info_page_up == 1)
413 {
414 buffer[*count] = 1;
415 *count += 1;
416 }
417
418 // cri sel update
419 chk_cri_sel_update(&cri_sel_up);
420 if (cri_sel_up == 1)
421 {
422 buffer[*count] = 2;
423 *count += 1;
424 }
425
426 // cri sensor update
427 buffer[*count] = 3;
428 *count += 1;
429
430 return 0;
431}
432
Vijay Khemka63c99be2020-05-27 19:14:35 -0700433int plat_udbg_get_post_desc(uint8_t index, uint8_t* next, uint8_t phase,
434 uint8_t* end, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800435{
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700436 nlohmann::json postObj;
437 std::string postCode;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800438
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700439 /* Get post description data stored in json file */
440 std::ifstream file(JSON_POST_DATA_FILE);
441 if (file)
442 {
443 file >> postObj;
444 file.close();
445 }
446 else
447 {
448 phosphor::logging::log<phosphor::logging::level::ERR>(
449 "Post code description file not found",
450 phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE));
451 return -1;
452 }
453
454 std::string phaseStr = "PhaseAny";
455 if (postObj.find(phaseStr) == postObj.end())
456 {
457 phaseStr = "Phase" + std::to_string(phase);
458 }
459
460 if (postObj.find(phaseStr) == postObj.end())
461 {
462 phosphor::logging::log<phosphor::logging::level::ERR>(
463 "Post code phase not available",
464 phosphor::logging::entry("PHASE=%d", phase));
465 return -1;
466 }
467
468 auto phaseObj = postObj[phaseStr];
469 int phaseSize = phaseObj.size();
470
471 for (int i = 0; i < phaseSize; i++)
472 {
473 postCode = phaseObj[i][0];
474 if (index == stoul(postCode, nullptr, 16))
475 {
476 std::string postDesc = phaseObj[i][1];
477 *length = postDesc.size();
478 memcpy(buffer, postDesc.data(), *length);
479 buffer[*length] = '\0';
480
481 if (phaseSize != i + 1)
482 {
483 postCode = phaseObj[i + 1][0];
484 *next = stoul(postCode, nullptr, 16);
485 *end = 0;
486 }
487 else
488 {
489 if (postObj.size() != phase)
490 {
491 std::string nextPhaseStr =
492 "Phase" + std::to_string(phase + 1);
493 postCode = postObj[nextPhaseStr][0][0];
494 *next = stoul(postCode, nullptr, 16);
495 *end = 0;
496 }
497 else
498 {
499 *next = 0xff;
500 *end = 1;
501 }
502 }
503
504 return 0;
505 }
506 }
507
508 phosphor::logging::log<phosphor::logging::level::ERR>(
509 "Post code description data not available",
510 phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index));
511 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800512}
513
Vijay Khemka63c99be2020-05-27 19:14:35 -0700514int plat_udbg_get_gpio_desc(uint8_t index, uint8_t* next, uint8_t* level,
515 uint8_t* def, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800516{
Vijay Khemka38183d62019-08-28 16:19:33 -0700517 nlohmann::json gpioObj;
518 std::string gpioPin;
519
520 /* Get gpio data stored in json file */
521 std::ifstream file(JSON_GPIO_DATA_FILE);
522 if (file)
523 {
524 file >> gpioObj;
525 file.close();
526 }
527 else
528 {
529 phosphor::logging::log<phosphor::logging::level::ERR>(
530 "GPIO pin description file not found",
531 phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s",
532 JSON_GPIO_DATA_FILE));
533 return -1;
534 }
535
536 if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end())
537 {
538 phosphor::logging::log<phosphor::logging::level::ERR>(
539 "GPIO pin details not available",
540 phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY));
541 return -1;
542 }
543
544 auto obj = gpioObj[DEBUG_GPIO_KEY];
545 int objSize = obj.size();
546
547 for (int i = 0; i < objSize; i++)
548 {
549 if (obj[i].size() != GPIO_ARRAY_SIZE)
550 {
551 phosphor::logging::log<phosphor::logging::level::ERR>(
552 "Size of gpio array is incorrect",
553 phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE));
554 return -1;
555 }
556
557 gpioPin = obj[i][GPIO_PIN_INDEX];
558 if (index == stoul(gpioPin, nullptr, 16))
559 {
560 if (objSize != i + 1)
561 {
562 gpioPin = obj[i + 1][GPIO_PIN_INDEX];
563 *next = stoul(gpioPin, nullptr, 16);
564 }
565 else
566 {
567 *next = 0xff;
568 }
569
570 *level = obj[i][GPIO_LEVEL_INDEX];
571 *def = obj[i][GPIO_DEF_INDEX];
572 std::string gpioDesc = obj[i][GPIO_DESC_INDEX];
573 *length = gpioDesc.size();
574 memcpy(buffer, gpioDesc.data(), *length);
575 buffer[*length] = '\0';
576
577 return 0;
578 }
579 }
580
581 phosphor::logging::log<phosphor::logging::level::ERR>(
582 "GPIO pin description data not available",
583 phosphor::logging::entry("GPIO_PIN=0x%x", index));
584 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800585}
586
Willy Tue39f9392022-06-15 13:24:20 -0700587static int udbg_get_cri_sel(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700588 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800589{
590 int len;
591 int ret;
Willy Tue39f9392022-06-15 13:24:20 -0700592 char line_buff[FRAME_PAGE_BUF_SIZE];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700593 const char* ptr;
594 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800595 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530596 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800597 static uint8_t pre_pos = FRU_ALL;
598 bool pos_changed = pre_pos != pos;
599
600 pre_pos = pos;
601
602 /* Revisit this */
603 fp = fopen("/mnt/data/cri_sel", "r");
604 if (fp)
605 {
606 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
607 (file_stat.st_mtime != frame_sel.mtime || pos_changed))
608 {
609 // initialize and clear frame
610 frame_sel.init(FRAME_BUFF_SIZE);
611 frame_sel.overwrite = 1;
612 frame_sel.max_page = 20;
613 frame_sel.mtime = file_stat.st_mtime;
614 snprintf(frame_sel.title, 32, "Cri SEL");
615
616 while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp))
617 {
618 // Remove newline
619 line_buff[strlen(line_buff) - 1] = '\0';
620 ptr = line_buff;
621 // Find message
622 ptr = strstr(ptr, "local0.err");
623 if (ptr == NULL)
624 {
625 continue;
626 }
627
628 if ((ptr = strrchr(ptr, ':')) == NULL)
629 {
630 continue;
631 }
632 len = strlen(ptr);
633 if (len > 2)
634 {
635 // to skip log string ": "
636 ptr += 2;
637 }
638 // Write new message
639 frame_sel.insert(ptr, 0);
640 }
641 }
642 fclose(fp);
643 }
644 else
645 {
646 // Title only
647 frame_sel.init(FRAME_BUFF_SIZE);
648 snprintf(frame_sel.title, 32, "Cri SEL");
649 frame_sel.mtime = 0;
650 }
651
652 if (page > frame_sel.pages)
653 {
654 return -1;
655 }
656
Vijay Khemka63c99be2020-05-27 19:14:35 -0700657 ret = frame_sel.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800658 if (ret < 0)
659 {
660 *count = 0;
661 return -1;
662 }
663 *count = (uint8_t)ret;
664
665 if (page < frame_sel.pages)
666 *next = page + 1;
667 else
668 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
669 // last page
670
671 return 0;
672}
673
Willy Tue39f9392022-06-15 13:24:20 -0700674static int udbg_get_cri_sensor(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700675 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800676{
Vijay Khemka427b2762019-12-12 12:49:25 -0800677 int ret;
678 double fvalue;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530679 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800680
681 if (page == 1)
682 {
683 // Only update frame data while getting page 1
684
685 // initialize and clear frame
686 frame_snr.init(FRAME_BUFF_SIZE);
687 snprintf(frame_snr.title, 32, "CriSensor");
Vijay Khemka427b2762019-12-12 12:49:25 -0800688
689 nlohmann::json senObj;
690
691 /* Get critical sensor names stored in json file */
692 std::ifstream file(JSON_SENSOR_NAMES_FILE);
693 if (file)
694 {
695 file >> senObj;
696 file.close();
697 }
698 else
699 {
700 phosphor::logging::log<phosphor::logging::level::ERR>(
701 "Critical Sensor names file not found",
702 phosphor::logging::entry("CRI_SENSOR_NAMES_FILE=%s",
703 JSON_SENSOR_NAMES_FILE));
704 return -1;
705 }
706
707 /* Get sensors values for all critical sensors */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700708 for (auto& j : senObj.items())
Vijay Khemka427b2762019-12-12 12:49:25 -0800709 {
710 std::string senName = j.key();
711 auto val = j.value();
712
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530713 if (senName[0] == '_')
714 {
715 senName = std::to_string(pos) + senName;
716 }
717
Vijay Khemka427b2762019-12-12 12:49:25 -0800718 if (ipmi::storage::getSensorValue(senName, fvalue) == 0)
719 {
720 std::stringstream ss;
Vijay Khemkaf43fad42019-12-26 11:47:58 -0800721 int prec = 0; // Default value
722
723 if (val.find("precision") != val.end())
724 prec = val["precision"];
725
726 ss << std::fixed << std::setprecision(prec) << fvalue;
Vijay Khemka427b2762019-12-12 12:49:25 -0800727
728 std::string senStr;
729 if (val.find("short_name") != val.end())
730 senStr = val["short_name"];
731 else
732 senStr = senName;
733
734 senStr += ss.str();
Vijay Khemka58bd5d82019-12-13 11:05:56 -0800735
736 /* Get unit string for sensor and append in output */
737 std::string unitStr;
738 if (ipmi::storage::getSensorUnit(senName, unitStr) == 0)
739 senStr += unitStr;
740
Vijay Khemka427b2762019-12-12 12:49:25 -0800741 frame_snr.append(senStr.c_str(), 0);
742 }
743 else
744 {
745 phosphor::logging::log<phosphor::logging::level::INFO>(
746 "Critical sensor not found",
747 phosphor::logging::entry("CRI_SENSOR_NAME=%s",
748 senName.c_str()));
749 }
750 }
751
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800752 } // End of update frame
753
754 if (page > frame_snr.pages)
755 {
756 return -1;
757 }
758
Vijay Khemka63c99be2020-05-27 19:14:35 -0700759 ret = frame_snr.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800760 if (ret < 0)
761 {
762 *count = 0;
763 return -1;
764 }
765 *count = (uint8_t)ret;
766
767 if (page < frame_snr.pages)
768 *next = page + 1;
769 else
770 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
771 // last page
772
773 return 0;
774}
775
Vijay Khemka63c99be2020-05-27 19:14:35 -0700776static int getBiosVer(std::string& ver)
Vijay Khemka88884b82019-08-27 15:23:07 -0700777{
778 nlohmann::json appObj;
779
780 std::ifstream file(JSON_APP_DATA_FILE);
781 if (file)
782 {
783 file >> appObj;
784 file.close();
785 if (appObj.find(KEY_SYSFW_VER) != appObj.end())
786 {
787 ver = appObj[KEY_SYSFW_VER].get<std::string>();
788 return 0;
789 }
790 }
791
792 return -1;
793}
794
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530795int sendBicCmd(uint8_t netFn, uint8_t cmd, uint8_t bicAddr,
796 std::vector<uint8_t>& cmdData, std::vector<uint8_t>& respData)
797{
798 static constexpr uint8_t lun = 0;
799
800 auto bus = getSdBus();
801
802 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
803 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
804 "org.openbmc.Ipmb", "sendRequest");
805 method.append(bicAddr, netFn, lun, cmd, cmdData);
806
807 auto reply = bus->call(method);
808 if (reply.is_method_error())
809 {
810 phosphor::logging::log<phosphor::logging::level::ERR>(
811 "Error reading from BIC");
812 return -1;
813 }
814
815 IpmbMethodType resp;
816 reply.read(resp);
817
818 respData =
819 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
820
821 return 0;
822}
823
Vijay Khemka63c99be2020-05-27 19:14:35 -0700824int sendMeCmd(uint8_t netFn, uint8_t cmd, std::vector<uint8_t>& cmdData,
825 std::vector<uint8_t>& respData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -0700826{
827 auto bus = getSdBus();
828
829 if (DEBUG)
830 {
831 std::cout << "ME NetFn:cmd " << (int)netFn << ":" << (int)cmd << "\n";
832 std::cout << "ME req data: ";
833 for (auto d : cmdData)
834 {
835 std::cout << d << " ";
836 }
837 std::cout << "\n";
838 }
839
840 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
841 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
842 "org.openbmc.Ipmb", "sendRequest");
843 method.append(meAddress, netFn, lun, cmd, cmdData);
844
845 auto reply = bus->call(method);
846 if (reply.is_method_error())
847 {
848 phosphor::logging::log<phosphor::logging::level::ERR>(
849 "Error reading from ME");
850 return -1;
851 }
852
853 IpmbMethodType resp;
854 reply.read(resp);
855
856 respData =
857 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
858
859 if (DEBUG)
860 {
861 std::cout << "ME resp data: ";
862 for (auto d : respData)
863 {
864 std::cout << d << " ";
865 }
866 std::cout << "\n";
867 }
868
869 return 0;
870}
871
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530872static int getMeStatus(std::string& status, size_t pos)
Vijay Khemka317999d2020-01-02 13:43:42 -0800873{
874 uint8_t cmd = 0x01; // Get Device id command
875 uint8_t netFn = 0x06; // Netfn for APP
876 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
877 std::vector<uint8_t> cmdData;
878
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530879 uint8_t meAddr = meAddress;
880 bool platform = isMultiHostPlatform();
881 if (platform == true)
882 {
883 meAddr = ((pos - 1) << 2);
884 }
885
Vijay Khemka317999d2020-01-02 13:43:42 -0800886 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
887 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
888 "org.openbmc.Ipmb", "sendRequest");
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530889 method.append(meAddr, netFn, lun, cmd, cmdData);
Vijay Khemka317999d2020-01-02 13:43:42 -0800890
891 auto reply = bus->call(method);
892 if (reply.is_method_error())
893 {
894 std::cerr << "Error reading from ME\n";
895 return -1;
896 }
897
898 IpmbMethodType resp;
899 reply.read(resp);
900
901 std::vector<uint8_t> data;
902 data = std::get<5>(resp);
903
904 if (DEBUG)
905 {
906 std::cout << "ME Get ID: ";
907 for (size_t d : data)
908 {
909 std::cout << d << " ";
910 }
911 std::cout << "\n";
912 }
913
914 if (data[2] & 0x80)
915 status = "recovery mode";
916 else
917 status = "operation mode";
918
919 return 0;
920}
921
Willy Tue39f9392022-06-15 13:24:20 -0700922static int udbg_get_info_page(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700923 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800924{
Willy Tue39f9392022-06-15 13:24:20 -0700925 char line_buff[1000];
926 [[maybe_unused]] char* pres_dev = line_buff;
927 [[maybe_unused]] size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800928 int ret;
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530929 std::string serialName = "SerialNumber";
930 std::string partName = "PartNumber";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800931 std::string verDel = "VERSION=";
932 std::string verPath = "/etc/os-release";
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530933 size_t hostPosition;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800934
935 if (page == 1)
936 {
937 // Only update frame data while getting page 1
938
939 // initialize and clear frame
940 frame_info.init(FRAME_BUFF_SIZE);
941 snprintf(frame_info.title, 32, "SYS_Info");
942
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530943 bool platform = isMultiHostPlatform();
944 if (platform == true)
945 {
946 hostPosition = getSelectorPosition();
947 }
948
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530949 if (hostPosition == BMC_POSITION || hostInstances == "0")
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530950 {
951 frame_info.append("FRU:spb", 0);
952 }
953 else if (hostPosition != BMC_POSITION && hostPosition <= MAX_HOST_POS)
954 {
955 std::string data = "FRU:slot" + std::to_string(hostPosition);
956 frame_info.append(data.c_str(), 0);
957 }
958
959 // FRU
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800960 std::string data;
961 frame_info.append("SN:", 0);
962 if (getFruData(data, serialName) != 0)
963 {
964 data = "Not Found";
965 }
966 frame_info.append(data.c_str(), 1);
967 frame_info.append("PN:", 0);
968 if (getFruData(data, partName) != 0)
969 {
970 data = "Not Found";
971 }
972 frame_info.append(data.c_str(), 1);
973
974 // LAN
975 getNetworkData(3, line_buff);
976 frame_info.append("BMC_IP:", 0);
977 frame_info.append(line_buff, 1);
978 getNetworkData(59, line_buff);
979 frame_info.append("BMC_IPv6:", 0);
980 frame_info.append(line_buff, 1);
981
982 // BMC ver
983 std::ifstream file(verPath);
984 if (file)
985 {
986 std::string line;
987 while (std::getline(file, line))
988 {
989 if (line.find(verDel) != std::string::npos)
990 {
991 std::string bmcVer = line.substr(verDel.size());
992 frame_info.append("BMC_FW_ver:", 0);
993 frame_info.append(bmcVer.c_str(), 1);
994 break;
995 }
996 }
997 }
998
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530999 if (hostPosition != BMC_POSITION)
Vijay Khemka88884b82019-08-27 15:23:07 -07001000 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301001 // BIOS ver
1002 std::string biosVer;
1003 if (getBiosVer(biosVer) == 0)
1004 {
1005 frame_info.append("BIOS_FW_ver:", 0);
1006 frame_info.append(biosVer.c_str(), 1);
1007 }
1008 // ME status
1009 std::string meStatus;
1010 if (getMeStatus(meStatus, pos) != 0)
1011 {
1012 phosphor::logging::log<phosphor::logging::level::WARNING>(
1013 "Reading ME status failed");
1014 meStatus = "unknown";
1015 }
1016 frame_info.append("ME_status:", 0);
1017 frame_info.append(meStatus.c_str(), 1);
Vijay Khemka88884b82019-08-27 15:23:07 -07001018 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001019
Vijay Khemka317999d2020-01-02 13:43:42 -08001020 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001021 // Board ID
1022
1023 // Battery - Use Escape sequence
1024 frame_info.append("Battery:", 0);
1025 frame_info.append(ESC_BAT " ", 1);
1026 // frame_info.append(&frame_info, esc_bat, 1);
1027
1028 // MCU Version - Use Escape sequence
1029 frame_info.append("MCUbl_ver:", 0);
1030 frame_info.append(ESC_MCU_BL_VER, 1);
1031 frame_info.append("MCU_ver:", 0);
1032 frame_info.append(ESC_MCU_RUN_VER, 1);
1033
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001034 // Sys config present device
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301035 if (hostPosition != BMC_POSITION)
1036 {
1037 frame_info.append("Sys Conf. info:", 0);
1038
1039 // Dimm info
1040 std::vector<std::string> data;
1041 sysConfig(data, pos);
1042 for (auto& info : data)
1043 {
1044 frame_info.append(info.c_str(), 1);
1045 }
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301046
1047 // Processor info
1048 std::string result;
1049 procInfo(result, pos);
1050 frame_info.append(result.c_str(), 1);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301051 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001052
1053 } // End of update frame
1054
1055 if (page > frame_info.pages)
1056 {
1057 return -1;
1058 }
1059
Vijay Khemka63c99be2020-05-27 19:14:35 -07001060 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001061 if (ret < 0)
1062 {
1063 *count = 0;
1064 return -1;
1065 }
1066 *count = (uint8_t)ret;
1067
1068 if (page < frame_info.pages)
1069 *next = page + 1;
1070 else
1071 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
1072 // last page
1073
1074 return 0;
1075}
1076
Vijay Khemka63c99be2020-05-27 19:14:35 -07001077int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
1078 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001079{
1080 switch (frame)
1081 {
1082 case 1: // info_page
1083 return udbg_get_info_page(frame, page, next, count, buffer);
1084 case 2: // critical SEL
1085 return udbg_get_cri_sel(frame, page, next, count, buffer);
1086 case 3: // critical Sensor
1087 return udbg_get_cri_sensor(frame, page, next, count, buffer);
1088 default:
1089 return -1;
1090 }
1091}
1092
1093static uint8_t panel_main(uint8_t item)
1094{
1095 // Update item list when select item 0
1096 switch (item)
1097 {
1098 case 1:
1099 return panels[PANEL_BOOT_ORDER].select(0);
1100 case 2:
1101 return panels[PANEL_POWER_POLICY].select(0);
1102 default:
1103 return PANEL_MAIN;
1104 }
1105}
1106
Willy Tue39f9392022-06-15 13:24:20 -07001107static uint8_t panel_boot_order(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001108{
Willy Tue39f9392022-06-15 13:24:20 -07001109 /* To be implemented */
1110#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001111 int i;
1112 unsigned char buff[MAX_VALUE_LEN], pickup, len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301113 size_t pos = plat_get_fru_sel();
Willy Tue39f9392022-06-15 13:24:20 -07001114 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
1115 {
1116 if (item > 0 && item < SIZE_BOOT_ORDER)
1117 {
1118 pickup = buff[item];
1119 while (item > 1)
1120 {
1121 buff[item] = buff[item - 1];
1122 item--;
1123 }
1124 buff[item] = pickup;
1125 buff[0] |= 0x80;
1126 pal_set_boot_order(pos, buff, buff, &len);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001127
Willy Tue39f9392022-06-15 13:24:20 -07001128 // refresh items
1129 return panels[PANEL_BOOT_ORDER].select(0);
1130 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001131
Willy Tue39f9392022-06-15 13:24:20 -07001132 // '*': boot flags valid, BIOS has not yet read
1133 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32, "Boot Order%c",
1134 (buff[0] & 0x80) ? '*' : '\0');
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001135
Willy Tue39f9392022-06-15 13:24:20 -07001136 for (i = 1; i < SIZE_BOOT_ORDER; i++)
1137 {
1138 switch (buff[i])
1139 {
1140 case 0x0:
1141 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1142 " USB device");
1143 break;
1144 case 0x1:
1145 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1146 " Network v4");
1147 break;
1148 case (0x1 | 0x8):
1149 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1150 " Network v6");
1151 break;
1152 case 0x2:
1153 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1154 " SATA HDD");
1155 break;
1156 case 0x3:
1157 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1158 " SATA-CDROM");
1159 break;
1160 case 0x4:
1161 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1162 " Other");
1163 break;
1164 default:
1165 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
1166 break;
1167 }
1168 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001169
Willy Tue39f9392022-06-15 13:24:20 -07001170 // remove empty items
1171 for (i--;
1172 (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0);
1173 i--)
1174 ;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001175
Willy Tue39f9392022-06-15 13:24:20 -07001176 panels[PANEL_BOOT_ORDER].item_num = i;
1177 }
1178 else
1179 {
1180 panels[PANEL_BOOT_ORDER].item_num = 0;
1181 }
1182#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001183 return PANEL_BOOT_ORDER;
1184}
1185
Willy Tue39f9392022-06-15 13:24:20 -07001186static uint8_t panel_power_policy(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001187{
Willy Tue39f9392022-06-15 13:24:20 -07001188/* To be cleaned */
1189#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001190 uint8_t buff[32] = {0};
1191 uint8_t res_len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301192 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001193 uint8_t policy;
Willy Tue39f9392022-06-15 13:24:20 -07001194 uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1195 POWER_CFG_OFF};
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001196
Willy Tue39f9392022-06-15 13:24:20 -07001197 if (pos != FRU_ALL)
1198 {
1199 if (item > 0 && item <= sizeof(pwr_policy_item_map))
1200 {
1201 policy = pwr_policy_item_map[item - 1];
1202 pal_set_power_restore_policy(pos, &policy, NULL);
1203 }
1204 pal_get_chassis_status(pos, NULL, buff, &res_len);
1205 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1206 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32, "%cPower On",
1207 policy == POWER_CFG_ON ? '*' : ' ');
1208 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32, "%cLast State",
1209 policy == POWER_CFG_LPS ? '*' : ' ');
1210 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32, "%cPower Off",
1211 policy == POWER_CFG_OFF ? '*' : ' ');
1212 panels[PANEL_POWER_POLICY].item_num = 3;
1213 }
1214 else
1215 {
1216 panels[PANEL_POWER_POLICY].item_num = 0;
1217 }
1218#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001219 return PANEL_POWER_POLICY;
1220}
1221
1222int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001223 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001224{
1225 if (panel > panelNum || panel < PANEL_MAIN)
1226 return IPMI_CC_PARM_OUT_OF_RANGE;
1227
1228 // No more item; End of item list
1229 if (item > panels[panel].item_num)
1230 return IPMI_CC_PARM_OUT_OF_RANGE;
1231
1232 switch (operation)
1233 {
1234 case 0: // Get Description
1235 break;
1236 case 1: // Select item
1237 panel = panels[panel].select(item);
1238 item = 0;
1239 break;
1240 case 2: // Back
1241 panel = panels[panel].parent;
1242 item = 0;
1243 break;
1244 default:
1245 return IPMI_CC_PARM_OUT_OF_RANGE;
1246 }
1247
1248 buffer[0] = panel;
1249 buffer[1] = item;
1250 buffer[2] = strlen(panels[panel].item_str[item]);
1251 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1252 {
1253 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1254 }
1255 *count = buffer[2] + 3;
1256 return IPMI_CC_OK;
1257}
1258
1259} // end of namespace ipmi