blob: 8b6c6e5e2a9d0ace73dd7486c053546996271e0e [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
Potin Lai2ad53982022-10-27 17:02:51 +0800872#ifdef ME_SUPPORT
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530873static int getMeStatus(std::string& status, size_t pos)
Vijay Khemka317999d2020-01-02 13:43:42 -0800874{
875 uint8_t cmd = 0x01; // Get Device id command
876 uint8_t netFn = 0x06; // Netfn for APP
877 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
878 std::vector<uint8_t> cmdData;
879
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530880 uint8_t meAddr = meAddress;
881 bool platform = isMultiHostPlatform();
882 if (platform == true)
883 {
884 meAddr = ((pos - 1) << 2);
885 }
886
Vijay Khemka317999d2020-01-02 13:43:42 -0800887 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
888 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
889 "org.openbmc.Ipmb", "sendRequest");
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530890 method.append(meAddr, netFn, lun, cmd, cmdData);
Vijay Khemka317999d2020-01-02 13:43:42 -0800891
892 auto reply = bus->call(method);
893 if (reply.is_method_error())
894 {
895 std::cerr << "Error reading from ME\n";
896 return -1;
897 }
898
899 IpmbMethodType resp;
900 reply.read(resp);
901
902 std::vector<uint8_t> data;
903 data = std::get<5>(resp);
904
905 if (DEBUG)
906 {
907 std::cout << "ME Get ID: ";
908 for (size_t d : data)
909 {
910 std::cout << d << " ";
911 }
912 std::cout << "\n";
913 }
914
915 if (data[2] & 0x80)
916 status = "recovery mode";
917 else
918 status = "operation mode";
919
920 return 0;
921}
Potin Lai2ad53982022-10-27 17:02:51 +0800922#endif
Vijay Khemka317999d2020-01-02 13:43:42 -0800923
Willy Tue39f9392022-06-15 13:24:20 -0700924static int udbg_get_info_page(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700925 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800926{
Willy Tue39f9392022-06-15 13:24:20 -0700927 char line_buff[1000];
928 [[maybe_unused]] char* pres_dev = line_buff;
929 [[maybe_unused]] size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800930 int ret;
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530931 std::string serialName = "SerialNumber";
932 std::string partName = "PartNumber";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800933 std::string verDel = "VERSION=";
934 std::string verPath = "/etc/os-release";
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530935 size_t hostPosition;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800936
937 if (page == 1)
938 {
939 // Only update frame data while getting page 1
940
941 // initialize and clear frame
942 frame_info.init(FRAME_BUFF_SIZE);
943 snprintf(frame_info.title, 32, "SYS_Info");
944
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530945 bool platform = isMultiHostPlatform();
946 if (platform == true)
947 {
948 hostPosition = getSelectorPosition();
949 }
950
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530951 if (hostPosition == BMC_POSITION || hostInstances == "0")
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530952 {
953 frame_info.append("FRU:spb", 0);
954 }
955 else if (hostPosition != BMC_POSITION && hostPosition <= MAX_HOST_POS)
956 {
957 std::string data = "FRU:slot" + std::to_string(hostPosition);
958 frame_info.append(data.c_str(), 0);
959 }
960
961 // FRU
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800962 std::string data;
963 frame_info.append("SN:", 0);
964 if (getFruData(data, serialName) != 0)
965 {
966 data = "Not Found";
967 }
968 frame_info.append(data.c_str(), 1);
969 frame_info.append("PN:", 0);
970 if (getFruData(data, partName) != 0)
971 {
972 data = "Not Found";
973 }
974 frame_info.append(data.c_str(), 1);
975
976 // LAN
977 getNetworkData(3, line_buff);
978 frame_info.append("BMC_IP:", 0);
979 frame_info.append(line_buff, 1);
980 getNetworkData(59, line_buff);
981 frame_info.append("BMC_IPv6:", 0);
982 frame_info.append(line_buff, 1);
983
984 // BMC ver
985 std::ifstream file(verPath);
986 if (file)
987 {
988 std::string line;
989 while (std::getline(file, line))
990 {
991 if (line.find(verDel) != std::string::npos)
992 {
993 std::string bmcVer = line.substr(verDel.size());
994 frame_info.append("BMC_FW_ver:", 0);
995 frame_info.append(bmcVer.c_str(), 1);
996 break;
997 }
998 }
999 }
1000
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301001 if (hostPosition != BMC_POSITION)
Vijay Khemka88884b82019-08-27 15:23:07 -07001002 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301003 // BIOS ver
1004 std::string biosVer;
1005 if (getBiosVer(biosVer) == 0)
1006 {
1007 frame_info.append("BIOS_FW_ver:", 0);
1008 frame_info.append(biosVer.c_str(), 1);
1009 }
Potin Lai2ad53982022-10-27 17:02:51 +08001010
1011#ifdef ME_SUPPORT
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301012 // ME status
1013 std::string meStatus;
1014 if (getMeStatus(meStatus, pos) != 0)
1015 {
1016 phosphor::logging::log<phosphor::logging::level::WARNING>(
1017 "Reading ME status failed");
1018 meStatus = "unknown";
1019 }
1020 frame_info.append("ME_status:", 0);
1021 frame_info.append(meStatus.c_str(), 1);
Potin Lai2ad53982022-10-27 17:02:51 +08001022#endif
Vijay Khemka88884b82019-08-27 15:23:07 -07001023 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001024
Vijay Khemka317999d2020-01-02 13:43:42 -08001025 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001026 // Board ID
1027
1028 // Battery - Use Escape sequence
1029 frame_info.append("Battery:", 0);
1030 frame_info.append(ESC_BAT " ", 1);
1031 // frame_info.append(&frame_info, esc_bat, 1);
1032
1033 // MCU Version - Use Escape sequence
1034 frame_info.append("MCUbl_ver:", 0);
1035 frame_info.append(ESC_MCU_BL_VER, 1);
1036 frame_info.append("MCU_ver:", 0);
1037 frame_info.append(ESC_MCU_RUN_VER, 1);
1038
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001039 // Sys config present device
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301040 if (hostPosition != BMC_POSITION)
1041 {
1042 frame_info.append("Sys Conf. info:", 0);
1043
1044 // Dimm info
1045 std::vector<std::string> data;
1046 sysConfig(data, pos);
1047 for (auto& info : data)
1048 {
1049 frame_info.append(info.c_str(), 1);
1050 }
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301051
1052 // Processor info
1053 std::string result;
1054 procInfo(result, pos);
1055 frame_info.append(result.c_str(), 1);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301056 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001057
1058 } // End of update frame
1059
1060 if (page > frame_info.pages)
1061 {
1062 return -1;
1063 }
1064
Vijay Khemka63c99be2020-05-27 19:14:35 -07001065 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001066 if (ret < 0)
1067 {
1068 *count = 0;
1069 return -1;
1070 }
1071 *count = (uint8_t)ret;
1072
1073 if (page < frame_info.pages)
1074 *next = page + 1;
1075 else
1076 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
1077 // last page
1078
1079 return 0;
1080}
1081
Vijay Khemka63c99be2020-05-27 19:14:35 -07001082int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
1083 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001084{
1085 switch (frame)
1086 {
1087 case 1: // info_page
1088 return udbg_get_info_page(frame, page, next, count, buffer);
1089 case 2: // critical SEL
1090 return udbg_get_cri_sel(frame, page, next, count, buffer);
1091 case 3: // critical Sensor
1092 return udbg_get_cri_sensor(frame, page, next, count, buffer);
1093 default:
1094 return -1;
1095 }
1096}
1097
1098static uint8_t panel_main(uint8_t item)
1099{
1100 // Update item list when select item 0
1101 switch (item)
1102 {
1103 case 1:
1104 return panels[PANEL_BOOT_ORDER].select(0);
1105 case 2:
1106 return panels[PANEL_POWER_POLICY].select(0);
1107 default:
1108 return PANEL_MAIN;
1109 }
1110}
1111
Willy Tue39f9392022-06-15 13:24:20 -07001112static uint8_t panel_boot_order(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001113{
Willy Tue39f9392022-06-15 13:24:20 -07001114 /* To be implemented */
1115#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001116 int i;
1117 unsigned char buff[MAX_VALUE_LEN], pickup, len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301118 size_t pos = plat_get_fru_sel();
Willy Tue39f9392022-06-15 13:24:20 -07001119 if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0)
1120 {
1121 if (item > 0 && item < SIZE_BOOT_ORDER)
1122 {
1123 pickup = buff[item];
1124 while (item > 1)
1125 {
1126 buff[item] = buff[item - 1];
1127 item--;
1128 }
1129 buff[item] = pickup;
1130 buff[0] |= 0x80;
1131 pal_set_boot_order(pos, buff, buff, &len);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001132
Willy Tue39f9392022-06-15 13:24:20 -07001133 // refresh items
1134 return panels[PANEL_BOOT_ORDER].select(0);
1135 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001136
Willy Tue39f9392022-06-15 13:24:20 -07001137 // '*': boot flags valid, BIOS has not yet read
1138 snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32, "Boot Order%c",
1139 (buff[0] & 0x80) ? '*' : '\0');
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001140
Willy Tue39f9392022-06-15 13:24:20 -07001141 for (i = 1; i < SIZE_BOOT_ORDER; i++)
1142 {
1143 switch (buff[i])
1144 {
1145 case 0x0:
1146 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1147 " USB device");
1148 break;
1149 case 0x1:
1150 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1151 " Network v4");
1152 break;
1153 case (0x1 | 0x8):
1154 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1155 " Network v6");
1156 break;
1157 case 0x2:
1158 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1159 " SATA HDD");
1160 break;
1161 case 0x3:
1162 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1163 " SATA-CDROM");
1164 break;
1165 case 0x4:
1166 snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32,
1167 " Other");
1168 break;
1169 default:
1170 panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0';
1171 break;
1172 }
1173 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001174
Willy Tue39f9392022-06-15 13:24:20 -07001175 // remove empty items
1176 for (i--;
1177 (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0);
1178 i--)
1179 ;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001180
Willy Tue39f9392022-06-15 13:24:20 -07001181 panels[PANEL_BOOT_ORDER].item_num = i;
1182 }
1183 else
1184 {
1185 panels[PANEL_BOOT_ORDER].item_num = 0;
1186 }
1187#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001188 return PANEL_BOOT_ORDER;
1189}
1190
Willy Tue39f9392022-06-15 13:24:20 -07001191static uint8_t panel_power_policy(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001192{
Willy Tue39f9392022-06-15 13:24:20 -07001193/* To be cleaned */
1194#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001195 uint8_t buff[32] = {0};
1196 uint8_t res_len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301197 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001198 uint8_t policy;
Willy Tue39f9392022-06-15 13:24:20 -07001199 uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1200 POWER_CFG_OFF};
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001201
Willy Tue39f9392022-06-15 13:24:20 -07001202 if (pos != FRU_ALL)
1203 {
1204 if (item > 0 && item <= sizeof(pwr_policy_item_map))
1205 {
1206 policy = pwr_policy_item_map[item - 1];
1207 pal_set_power_restore_policy(pos, &policy, NULL);
1208 }
1209 pal_get_chassis_status(pos, NULL, buff, &res_len);
1210 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1211 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32, "%cPower On",
1212 policy == POWER_CFG_ON ? '*' : ' ');
1213 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32, "%cLast State",
1214 policy == POWER_CFG_LPS ? '*' : ' ');
1215 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32, "%cPower Off",
1216 policy == POWER_CFG_OFF ? '*' : ' ');
1217 panels[PANEL_POWER_POLICY].item_num = 3;
1218 }
1219 else
1220 {
1221 panels[PANEL_POWER_POLICY].item_num = 0;
1222 }
1223#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001224 return PANEL_POWER_POLICY;
1225}
1226
1227int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001228 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001229{
1230 if (panel > panelNum || panel < PANEL_MAIN)
1231 return IPMI_CC_PARM_OUT_OF_RANGE;
1232
1233 // No more item; End of item list
1234 if (item > panels[panel].item_num)
1235 return IPMI_CC_PARM_OUT_OF_RANGE;
1236
1237 switch (operation)
1238 {
1239 case 0: // Get Description
1240 break;
1241 case 1: // Select item
1242 panel = panels[panel].select(item);
1243 item = 0;
1244 break;
1245 case 2: // Back
1246 panel = panels[panel].parent;
1247 item = 0;
1248 break;
1249 default:
1250 return IPMI_CC_PARM_OUT_OF_RANGE;
1251 }
1252
1253 buffer[0] = panel;
1254 buffer[1] = item;
1255 buffer[2] = strlen(panels[panel].item_str[item]);
1256 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1257 {
1258 memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]);
1259 }
1260 *count = buffer[2] + 3;
1261 return IPMI_CC_OK;
1262}
1263
1264} // end of namespace ipmi