blob: e2a0081a984ae076daf055cec142434f25c68ef0 [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
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +053017#include <commandutils.hpp>
Patrick Williams2405ae92023-05-10 07:50:09 -050018#include <usb-dbg.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 +053036} // namespace selector
37
Vijay Khemka427b2762019-12-12 12:49:25 -080038/* Declare storage functions used here */
39namespace storage
40{
Vijay Khemka63c99be2020-05-27 19:14:35 -070041int getSensorValue(std::string&, double&);
42int getSensorUnit(std::string&, std::string&);
Delphine CC Chiu2ca4aa02023-02-01 16:30:18 +080043int getSensorThreshold(std::string&, std::string&);
Vijay Khemka58bd5d82019-12-13 11:05:56 -080044} // namespace storage
Vijay Khemka427b2762019-12-12 12:49:25 -080045
Delphine CC Chiu7bb45922023-04-10 13:34:04 +080046namespace boot
47{
48std::tuple<std::string, std::string> objPath(size_t id);
49void setBootOrder(std::string bootObjPath, const std::vector<uint8_t>& bootSeq,
50 std::string hostName);
51void getBootOrder(std::string bootObjPath, std::vector<uint8_t>& bootSeq,
52 std::string hostName);
53} // namespace boot
54
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +053055void getMaxHostPosition(size_t& maxPosition)
Potin Laif24c78e2022-10-27 17:13:14 +080056{
57 try
58 {
59 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
Patrick Williams2405ae92023-05-10 07:50:09 -050060 std::string service = getService(*dbus, ipmi::selector::interface,
61 ipmi::selector::path);
62 Value variant = getDbusProperty(*dbus, service, ipmi::selector::path,
63 ipmi::selector::interface,
64 "MaxPosition");
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +053065 maxPosition = std::get<size_t>(variant);
Potin Laif24c78e2022-10-27 17:13:14 +080066 }
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +053067 catch (const std::exception& e)
Potin Laif24c78e2022-10-27 17:13:14 +080068 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +053069 lg2::error("Unable to get max host position - {MAXPOSITION}",
70 "MAXPOSITION", maxPosition);
71 throw e;
Potin Laif24c78e2022-10-27 17:13:14 +080072 }
Potin Laif24c78e2022-10-27 17:13:14 +080073}
74
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +053075void getSelectorPosition(size_t& hostPosition)
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053076{
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +053077 try
78 {
79 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
Patrick Williams2405ae92023-05-10 07:50:09 -050080 std::string service = getService(*dbus, ipmi::selector::interface,
81 ipmi::selector::path);
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +053082 Value variant = getDbusProperty(*dbus, service, ipmi::selector::path,
83 ipmi::selector::interface, "Position");
84 hostPosition = std::get<size_t>(variant);
85 }
86 catch (const std::exception& e)
87 {
88 lg2::error("Unable to get host position - {POSITION}", "POSITION",
89 hostPosition);
90 throw e;
91 }
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053092}
93
Vijay Khemkae7d23d02019-03-08 13:13:40 -080094static int panelNum = (sizeof(panels) / sizeof(struct ctrl_panel)) - 1;
95
96/* Returns the FRU the hand-switch is switched to. If it is switched to BMC
97 * it returns FRU_ALL. Note, if in err, it returns FRU_ALL */
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +053098static size_t plat_get_fru_sel()
Vijay Khemkae7d23d02019-03-08 13:13:40 -080099{
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530100 size_t position;
101 bool platform = isMultiHostPlatform();
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530102 if (platform == true)
103 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530104 getSelectorPosition(position);
105 if (position == BMC_POSITION)
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530106 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530107 return FRU_ALL;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530108 }
109 }
110 else
111 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530112 /* For Tiogapass it just return 1,
113 * can modify to support more platform */
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530114 position = 1;
115 }
116 return position;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800117}
118
119// return 0 on seccuess
120int frame::init(size_t size)
121{
122 // Reset status
123 idx_head = idx_tail = 0;
124 lines = 0;
125 esc_sts = 0;
126 pages = 1;
127
128 if (buf != NULL && max_size == size)
129 {
130 // reinit
131 return 0;
132 }
133
134 if (buf != NULL && max_size != size)
135 {
136 delete[] buf;
137 }
138 // Initialize Configuration
139 title[0] = '\0';
140 buf = new char[size];
141 max_size = size;
142 max_page = size;
143 line_per_page = 7;
144 line_width = 16;
145 overwrite = 0;
146
147 if (buf)
148 return 0;
149 else
150 return -1;
151}
152
153// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700154int frame::append(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800155{
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530156 const size_t buf_size = 128;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800157 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700158 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800159 int ret;
160
161 ret = parse(lbuf, buf_size, string, indent);
162
163 if (ret < 0)
164 return ret;
165
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800166 for (ptr = lbuf; *ptr != '\0'; ptr++)
167 {
168 if (isFull())
169 {
170 if (overwrite)
171 {
172 if (buf[idx_head] == LINE_DELIMITER)
173 lines--;
174 idx_head = (idx_head + 1) % max_size;
175 }
176 else
177 return -1;
178 }
179
180 buf[idx_tail] = *ptr;
181 if (*ptr == LINE_DELIMITER)
182 lines++;
183
184 idx_tail = (idx_tail + 1) % max_size;
185 }
186
187 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
188
189 if (pages > max_page)
190 pages = max_page;
191
192 return 0;
193}
194
195// return 0 on seccuess
Vijay Khemka63c99be2020-05-27 19:14:35 -0700196int frame::insert(const char* string, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800197{
198 const size_t buf_size = 128;
199 char lbuf[buf_size];
Vijay Khemka63c99be2020-05-27 19:14:35 -0700200 char* ptr;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800201 int ret;
202 int i;
203
204 ret = parse(lbuf, buf_size, string, indent);
205
206 if (ret < 0)
207 return ret;
208
209 for (i = strlen(lbuf) - 1; i >= 0; i--)
210 {
211 ptr = &lbuf[i];
212 if (isFull())
213 {
214 if (overwrite)
215 {
216 idx_tail = (idx_tail + max_size - 1) % max_size;
217 if (buf[idx_tail] == LINE_DELIMITER)
218 lines--;
219 }
220 else
221 return -1;
222 }
223
224 idx_head = (idx_head + max_size - 1) % max_size;
225
226 buf[idx_head] = *ptr;
227 if (*ptr == LINE_DELIMITER)
228 lines++;
229 }
230
231 pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0);
232
233 if (pages > max_page)
234 pages = max_page;
235
236 return 0;
237}
238
239// return page size
Vijay Khemka63c99be2020-05-27 19:14:35 -0700240int frame::getPage(int page, char* page_buf, size_t page_buf_size)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800241{
242 int ret;
243 uint16_t line = 0;
244 uint16_t idx, len;
245
246 if (buf == NULL)
247 return -1;
248
249 // 1-based page
250 if (page > pages || page < 1)
251 return -1;
252
Willy Tue39f9392022-06-15 13:24:20 -0700253 if (page_buf == NULL || page_buf_size == 0)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800254 return -1;
255
256 ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages);
257 len = strlen(page_buf);
258 if (ret < 0)
259 return -1;
260
261 line = 0;
262 idx = idx_head;
263 while (line < ((page - 1) * line_per_page) && idx != idx_tail)
264 {
265 if (buf[idx] == LINE_DELIMITER)
266 line++;
267 idx = (idx + 1) % max_size;
268 }
269
270 while (line < ((page)*line_per_page) && idx != idx_tail)
271 {
272 if (buf[idx] == LINE_DELIMITER)
273 {
274 line++;
275 }
276 else
277 {
278 page_buf[len++] = buf[idx];
279 if (len == (page_buf_size - 1))
280 {
281 break;
282 }
283 }
284 idx = (idx + 1) % max_size;
285 }
286
287 return len;
288}
289
290// return 1 for frame buffer full
291int frame::isFull()
292{
293 if (buf == NULL)
294 return -1;
295
296 if ((idx_tail + 1) % max_size == idx_head)
297 return 1;
298 else
299 return 0;
300}
301
302// return 1 for Escape Sequence
303int frame::isEscSeq(char chr)
304{
305 uint8_t curr_sts = esc_sts;
306
307 if (esc_sts == 0 && (chr == 0x1b))
308 esc_sts = 1; // Escape Sequence
309 else if (esc_sts == 1 && (chr == 0x5b))
310 esc_sts = 2; // Control Sequence Introducer(CSI)
311 else if (esc_sts == 1 && (chr != 0x5b))
312 esc_sts = 0;
313 else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e))
314 esc_sts = 0;
315
316 if (curr_sts || esc_sts)
317 return 1;
318 else
319 return 0;
320}
321
322// return 0 on success
Vijay Khemka63c99be2020-05-27 19:14:35 -0700323int frame::parse(char* lbuf, size_t buf_size, const char* input, int indent)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800324{
325 uint8_t pos, esc;
Willy Tue39f9392022-06-15 13:24:20 -0700326 size_t i;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800327 const char *in, *end;
328
329 if (buf == NULL || input == NULL)
330 return -1;
331
332 if (indent >= line_width || indent < 0)
333 return -1;
334
335 in = input;
336 end = in + strlen(input);
337 pos = 0; // line position
338 esc = 0; // escape state
339 i = 0; // buf index
340 while (in != end)
341 {
342 if (i >= buf_size)
343 break;
344
345 if (pos < indent)
346 {
347 // fill indent
348 lbuf[i++] = ' ';
349 pos++;
350 continue;
351 }
352
353 esc = isEscSeq(*in);
354
355 if (!esc && pos == line_width)
356 {
357 lbuf[i++] = LINE_DELIMITER;
358 pos = 0;
359 continue;
360 }
361
362 if (!esc)
363 pos++;
364
365 // fill input data
366 lbuf[i++] = *(in++);
367 }
368
369 // padding
370 while (pos <= line_width)
371 {
372 if (i >= buf_size)
373 break;
374 if (pos < line_width)
375 lbuf[i++] = ' ';
376 else
377 lbuf[i++] = LINE_DELIMITER;
378 pos++;
379 }
380
381 // full
382 if (i >= buf_size)
383 return -1;
384
385 lbuf[i++] = '\0';
386
387 return 0;
388}
389
Vijay Khemka63c99be2020-05-27 19:14:35 -0700390static int chk_cri_sel_update(uint8_t* cri_sel_up)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800391{
Vijay Khemka63c99be2020-05-27 19:14:35 -0700392 FILE* fp;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800393 struct stat file_stat;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530394 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800395 static uint8_t pre_pos = 0xff;
396
397 fp = fopen("/mnt/data/cri_sel", "r");
398 if (fp)
399 {
400 if ((stat("/mnt/data/cri_sel", &file_stat) == 0) &&
401 (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos))
402 {
403 *cri_sel_up = 1;
404 }
405 else
406 {
407 *cri_sel_up = 0;
408 }
409 fclose(fp);
410 }
411 else
412 {
413 if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos)
414 {
415 *cri_sel_up = 1;
416 }
417 else
418 {
419 *cri_sel_up = 0;
420 }
421 }
422 pre_pos = pos;
423 return 0;
424}
425
Vijay Khemka63c99be2020-05-27 19:14:35 -0700426int plat_udbg_get_frame_info(uint8_t* num)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800427{
428 *num = 3;
429 return 0;
430}
431
Vijay Khemka63c99be2020-05-27 19:14:35 -0700432int plat_udbg_get_updated_frames(uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800433{
434 uint8_t cri_sel_up = 0;
435 uint8_t info_page_up = 1;
436
437 *count = 0;
438
439 // info page update
440 if (info_page_up == 1)
441 {
442 buffer[*count] = 1;
443 *count += 1;
444 }
445
446 // cri sel update
447 chk_cri_sel_update(&cri_sel_up);
448 if (cri_sel_up == 1)
449 {
450 buffer[*count] = 2;
451 *count += 1;
452 }
453
454 // cri sensor update
455 buffer[*count] = 3;
456 *count += 1;
457
458 return 0;
459}
460
Vijay Khemka63c99be2020-05-27 19:14:35 -0700461int plat_udbg_get_post_desc(uint8_t index, uint8_t* next, uint8_t phase,
462 uint8_t* end, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800463{
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700464 nlohmann::json postObj;
465 std::string postCode;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800466
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700467 /* Get post description data stored in json file */
468 std::ifstream file(JSON_POST_DATA_FILE);
469 if (file)
470 {
471 file >> postObj;
472 file.close();
473 }
474 else
475 {
476 phosphor::logging::log<phosphor::logging::level::ERR>(
477 "Post code description file not found",
478 phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE));
479 return -1;
480 }
481
482 std::string phaseStr = "PhaseAny";
483 if (postObj.find(phaseStr) == postObj.end())
484 {
485 phaseStr = "Phase" + std::to_string(phase);
486 }
487
488 if (postObj.find(phaseStr) == postObj.end())
489 {
490 phosphor::logging::log<phosphor::logging::level::ERR>(
491 "Post code phase not available",
492 phosphor::logging::entry("PHASE=%d", phase));
493 return -1;
494 }
495
496 auto phaseObj = postObj[phaseStr];
497 int phaseSize = phaseObj.size();
498
499 for (int i = 0; i < phaseSize; i++)
500 {
501 postCode = phaseObj[i][0];
502 if (index == stoul(postCode, nullptr, 16))
503 {
504 std::string postDesc = phaseObj[i][1];
505 *length = postDesc.size();
506 memcpy(buffer, postDesc.data(), *length);
507 buffer[*length] = '\0';
508
509 if (phaseSize != i + 1)
510 {
511 postCode = phaseObj[i + 1][0];
512 *next = stoul(postCode, nullptr, 16);
513 *end = 0;
514 }
515 else
516 {
517 if (postObj.size() != phase)
518 {
Patrick Williams2405ae92023-05-10 07:50:09 -0500519 std::string nextPhaseStr = "Phase" +
520 std::to_string(phase + 1);
Vijay Khemkacc0d6d92019-08-27 14:51:17 -0700521 postCode = postObj[nextPhaseStr][0][0];
522 *next = stoul(postCode, nullptr, 16);
523 *end = 0;
524 }
525 else
526 {
527 *next = 0xff;
528 *end = 1;
529 }
530 }
531
532 return 0;
533 }
534 }
535
536 phosphor::logging::log<phosphor::logging::level::ERR>(
537 "Post code description data not available",
538 phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index));
539 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800540}
541
Vijay Khemka63c99be2020-05-27 19:14:35 -0700542int plat_udbg_get_gpio_desc(uint8_t index, uint8_t* next, uint8_t* level,
543 uint8_t* def, uint8_t* length, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800544{
Vijay Khemka38183d62019-08-28 16:19:33 -0700545 nlohmann::json gpioObj;
546 std::string gpioPin;
547
548 /* Get gpio data stored in json file */
549 std::ifstream file(JSON_GPIO_DATA_FILE);
550 if (file)
551 {
552 file >> gpioObj;
553 file.close();
554 }
555 else
556 {
557 phosphor::logging::log<phosphor::logging::level::ERR>(
558 "GPIO pin description file not found",
559 phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s",
560 JSON_GPIO_DATA_FILE));
561 return -1;
562 }
563
564 if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end())
565 {
566 phosphor::logging::log<phosphor::logging::level::ERR>(
567 "GPIO pin details not available",
568 phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY));
569 return -1;
570 }
571
572 auto obj = gpioObj[DEBUG_GPIO_KEY];
573 int objSize = obj.size();
574
575 for (int i = 0; i < objSize; i++)
576 {
577 if (obj[i].size() != GPIO_ARRAY_SIZE)
578 {
579 phosphor::logging::log<phosphor::logging::level::ERR>(
580 "Size of gpio array is incorrect",
581 phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE));
582 return -1;
583 }
584
585 gpioPin = obj[i][GPIO_PIN_INDEX];
586 if (index == stoul(gpioPin, nullptr, 16))
587 {
588 if (objSize != i + 1)
589 {
590 gpioPin = obj[i + 1][GPIO_PIN_INDEX];
591 *next = stoul(gpioPin, nullptr, 16);
592 }
593 else
594 {
595 *next = 0xff;
596 }
597
598 *level = obj[i][GPIO_LEVEL_INDEX];
599 *def = obj[i][GPIO_DEF_INDEX];
600 std::string gpioDesc = obj[i][GPIO_DESC_INDEX];
601 *length = gpioDesc.size();
602 memcpy(buffer, gpioDesc.data(), *length);
603 buffer[*length] = '\0';
604
605 return 0;
606 }
607 }
608
609 phosphor::logging::log<phosphor::logging::level::ERR>(
610 "GPIO pin description data not available",
611 phosphor::logging::entry("GPIO_PIN=0x%x", index));
612 return -1;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800613}
614
Willy Tue39f9392022-06-15 13:24:20 -0700615static int udbg_get_cri_sel(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700616 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800617{
Delphine CC Chiu7430e8d2023-03-09 16:32:40 +0800618 if (page == 1)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800619 {
Delphine CC Chiu7430e8d2023-03-09 16:32:40 +0800620 // initialize and clear frame
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800621 frame_sel.init(FRAME_BUFF_SIZE);
Delphine CC Chiu7430e8d2023-03-09 16:32:40 +0800622 frame_sel.overwrite = 1;
623 frame_sel.max_page = 20;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800624 snprintf(frame_sel.title, 32, "Cri SEL");
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800625
Delphine CC Chiu7430e8d2023-03-09 16:32:40 +0800626 static constexpr const auto depth = 0;
627 std::vector<std::string> paths;
628
629 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
630
631 auto mapperCall = dbus->new_method_call(
632 "xyz.openbmc_project.ObjectMapper",
633 "/xyz/openbmc_project/object_mapper",
634 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths");
635 static constexpr std::array<const char*, 1> interface = {
636 "xyz.openbmc_project.Logging.Entry"};
637 mapperCall.append("/", depth, interface);
638
639 try
640 {
641 auto reply = dbus->call(mapperCall);
642 reply.read(paths);
643 }
644 catch (sdbusplus::exception_t& e)
645 {
646 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
647 return -1;
648 }
649
650 std::string message;
651
652 // Iterate each loggings
653 for (const auto& path : paths)
654 {
655 Value variant = ipmi::getDbusProperty(
656 *dbus, "xyz.openbmc_project.Logging", path,
657 "xyz.openbmc_project.Logging.Entry", "Severity");
658
659 // Only filter critial sel
660 if (std::get<std::string>(variant) !=
661 "xyz.openbmc_project.Logging.Entry.Level.Critical")
662 {
663 continue;
664 }
665
666 variant = ipmi::getDbusProperty(
667 *dbus, "xyz.openbmc_project.Logging", path,
668 "xyz.openbmc_project.Logging.Entry", "Message");
669 message = std::get<std::string>(variant);
670
671 frame_sel.insert(message.c_str(), 0);
672 }
673 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800674 if (page > frame_sel.pages)
675 {
676 return -1;
677 }
Delphine CC Chiu7430e8d2023-03-09 16:32:40 +0800678 int ret = frame_sel.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800679 if (ret < 0)
680 {
681 *count = 0;
682 return -1;
683 }
684 *count = (uint8_t)ret;
685
686 if (page < frame_sel.pages)
687 *next = page + 1;
688 else
689 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
690 // last page
691
692 return 0;
693}
694
Willy Tue39f9392022-06-15 13:24:20 -0700695static int udbg_get_cri_sensor(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700696 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800697{
Vijay Khemka427b2762019-12-12 12:49:25 -0800698 int ret;
699 double fvalue;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530700 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800701
702 if (page == 1)
703 {
704 // Only update frame data while getting page 1
705
706 // initialize and clear frame
707 frame_snr.init(FRAME_BUFF_SIZE);
708 snprintf(frame_snr.title, 32, "CriSensor");
Vijay Khemka427b2762019-12-12 12:49:25 -0800709
710 nlohmann::json senObj;
711
712 /* Get critical sensor names stored in json file */
713 std::ifstream file(JSON_SENSOR_NAMES_FILE);
714 if (file)
715 {
716 file >> senObj;
717 file.close();
718 }
719 else
720 {
721 phosphor::logging::log<phosphor::logging::level::ERR>(
722 "Critical Sensor names file not found",
723 phosphor::logging::entry("CRI_SENSOR_NAMES_FILE=%s",
724 JSON_SENSOR_NAMES_FILE));
725 return -1;
726 }
727
728 /* Get sensors values for all critical sensors */
Vijay Khemka63c99be2020-05-27 19:14:35 -0700729 for (auto& j : senObj.items())
Vijay Khemka427b2762019-12-12 12:49:25 -0800730 {
731 std::string senName = j.key();
732 auto val = j.value();
733
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530734 if (senName[0] == '_')
735 {
736 senName = std::to_string(pos) + senName;
737 }
738
Vijay Khemka427b2762019-12-12 12:49:25 -0800739 if (ipmi::storage::getSensorValue(senName, fvalue) == 0)
740 {
741 std::stringstream ss;
Vijay Khemkaf43fad42019-12-26 11:47:58 -0800742 int prec = 0; // Default value
743
744 if (val.find("precision") != val.end())
745 prec = val["precision"];
746
747 ss << std::fixed << std::setprecision(prec) << fvalue;
Vijay Khemka427b2762019-12-12 12:49:25 -0800748
749 std::string senStr;
750 if (val.find("short_name") != val.end())
751 senStr = val["short_name"];
752 else
753 senStr = senName;
754
755 senStr += ss.str();
Vijay Khemka58bd5d82019-12-13 11:05:56 -0800756
757 /* Get unit string for sensor and append in output */
758 std::string unitStr;
759 if (ipmi::storage::getSensorUnit(senName, unitStr) == 0)
760 senStr += unitStr;
761
Delphine CC Chiu2ca4aa02023-02-01 16:30:18 +0800762 std::string thresholdStr;
Patrick Williams2405ae92023-05-10 07:50:09 -0500763 int ret = ipmi::storage::getSensorThreshold(senName,
764 thresholdStr);
Delphine CC Chiu2ca4aa02023-02-01 16:30:18 +0800765 if (ret < 0)
766 {
767 phosphor::logging::log<phosphor::logging::level::ERR>(
768 "Error getting critical sensor threshold status",
769 phosphor::logging::entry("CRI_SENSOR_NAME=%s",
770 senName.c_str()));
771 return -1;
772 }
773 if (thresholdStr.size() != 0)
774 {
775 senStr += ("/" + thresholdStr);
776 std::string senStrWithBlinkAndInvertColor =
777 ESC_ALT + senStr + ESC_RST;
778 frame_snr.append(senStrWithBlinkAndInvertColor.c_str(), 0);
779 }
780 else
781 {
782 frame_snr.append(senStr.c_str(), 0);
783 }
Vijay Khemka427b2762019-12-12 12:49:25 -0800784 }
785 else
786 {
787 phosphor::logging::log<phosphor::logging::level::INFO>(
788 "Critical sensor not found",
789 phosphor::logging::entry("CRI_SENSOR_NAME=%s",
790 senName.c_str()));
791 }
792 }
793
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800794 } // End of update frame
795
796 if (page > frame_snr.pages)
797 {
798 return -1;
799 }
800
Vijay Khemka63c99be2020-05-27 19:14:35 -0700801 ret = frame_snr.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800802 if (ret < 0)
803 {
804 *count = 0;
805 return -1;
806 }
807 *count = (uint8_t)ret;
808
809 if (page < frame_snr.pages)
810 *next = page + 1;
811 else
812 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
813 // last page
814
815 return 0;
816}
817
Bonnie Loe9baaff2022-11-08 16:36:21 +0800818static int getBiosVer(std::string& ver, size_t hostPosition)
Vijay Khemka88884b82019-08-27 15:23:07 -0700819{
820 nlohmann::json appObj;
821
822 std::ifstream file(JSON_APP_DATA_FILE);
823 if (file)
824 {
825 file >> appObj;
826 file.close();
Bonnie Loe9baaff2022-11-08 16:36:21 +0800827 std::string version_key = KEY_SYSFW_VER + std::to_string(hostPosition);
828
829 if (appObj.find(version_key) != appObj.end())
Vijay Khemka88884b82019-08-27 15:23:07 -0700830 {
Bonnie Loe9baaff2022-11-08 16:36:21 +0800831 ver = appObj[version_key].get<std::string>();
Vijay Khemka88884b82019-08-27 15:23:07 -0700832 return 0;
833 }
834 }
835
836 return -1;
837}
838
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530839int sendBicCmd(uint8_t netFn, uint8_t cmd, uint8_t bicAddr,
840 std::vector<uint8_t>& cmdData, std::vector<uint8_t>& respData)
841{
842 static constexpr uint8_t lun = 0;
843
844 auto bus = getSdBus();
845
846 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
847 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
848 "org.openbmc.Ipmb", "sendRequest");
849 method.append(bicAddr, netFn, lun, cmd, cmdData);
850
851 auto reply = bus->call(method);
852 if (reply.is_method_error())
853 {
854 phosphor::logging::log<phosphor::logging::level::ERR>(
855 "Error reading from BIC");
856 return -1;
857 }
858
859 IpmbMethodType resp;
860 reply.read(resp);
861
862 respData =
863 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
864
865 return 0;
866}
867
Vijay Khemka63c99be2020-05-27 19:14:35 -0700868int sendMeCmd(uint8_t netFn, uint8_t cmd, std::vector<uint8_t>& cmdData,
869 std::vector<uint8_t>& respData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -0700870{
871 auto bus = getSdBus();
872
873 if (DEBUG)
874 {
875 std::cout << "ME NetFn:cmd " << (int)netFn << ":" << (int)cmd << "\n";
876 std::cout << "ME req data: ";
877 for (auto d : cmdData)
878 {
879 std::cout << d << " ";
880 }
881 std::cout << "\n";
882 }
883
884 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
885 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
886 "org.openbmc.Ipmb", "sendRequest");
887 method.append(meAddress, netFn, lun, cmd, cmdData);
888
889 auto reply = bus->call(method);
890 if (reply.is_method_error())
891 {
892 phosphor::logging::log<phosphor::logging::level::ERR>(
893 "Error reading from ME");
894 return -1;
895 }
896
897 IpmbMethodType resp;
898 reply.read(resp);
899
900 respData =
901 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
902
903 if (DEBUG)
904 {
905 std::cout << "ME resp data: ";
906 for (auto d : respData)
907 {
908 std::cout << d << " ";
909 }
910 std::cout << "\n";
911 }
912
913 return 0;
914}
915
Willy Tue39f9392022-06-15 13:24:20 -0700916static int udbg_get_info_page(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700917 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800918{
Willy Tue39f9392022-06-15 13:24:20 -0700919 char line_buff[1000];
920 [[maybe_unused]] char* pres_dev = line_buff;
921 [[maybe_unused]] size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800922 int ret;
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530923 std::string serialName = "SerialNumber";
924 std::string partName = "PartNumber";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800925 std::string verDel = "VERSION=";
926 std::string verPath = "/etc/os-release";
BonnieLo-wiwynn21a79232023-03-09 16:42:48 +0800927 size_t hostPosition = 0;
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530928 size_t maxPosition;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800929
930 if (page == 1)
931 {
932 // Only update frame data while getting page 1
933
934 // initialize and clear frame
935 frame_info.init(FRAME_BUFF_SIZE);
936 snprintf(frame_info.title, 32, "SYS_Info");
937
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530938 bool platform = isMultiHostPlatform();
939 if (platform == true)
940 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530941 hostPosition = plat_get_fru_sel();
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530942 }
943
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530944 getMaxHostPosition(maxPosition);
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530945 if (hostPosition == BMC_POSITION || hostInstances == "0")
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530946 {
947 frame_info.append("FRU:spb", 0);
948 }
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530949 else if (hostPosition != BMC_POSITION && hostPosition <= maxPosition)
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530950 {
951 std::string data = "FRU:slot" + std::to_string(hostPosition);
952 frame_info.append(data.c_str(), 0);
953 }
954
955 // FRU
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800956 std::string data;
957 frame_info.append("SN:", 0);
958 if (getFruData(data, serialName) != 0)
959 {
960 data = "Not Found";
961 }
962 frame_info.append(data.c_str(), 1);
963 frame_info.append("PN:", 0);
964 if (getFruData(data, partName) != 0)
965 {
966 data = "Not Found";
967 }
968 frame_info.append(data.c_str(), 1);
969
970 // LAN
971 getNetworkData(3, line_buff);
972 frame_info.append("BMC_IP:", 0);
973 frame_info.append(line_buff, 1);
974 getNetworkData(59, line_buff);
975 frame_info.append("BMC_IPv6:", 0);
976 frame_info.append(line_buff, 1);
977
978 // BMC ver
979 std::ifstream file(verPath);
980 if (file)
981 {
982 std::string line;
983 while (std::getline(file, line))
984 {
985 if (line.find(verDel) != std::string::npos)
986 {
987 std::string bmcVer = line.substr(verDel.size());
988 frame_info.append("BMC_FW_ver:", 0);
989 frame_info.append(bmcVer.c_str(), 1);
990 break;
991 }
992 }
993 }
994
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530995 if (hostPosition != BMC_POSITION)
Vijay Khemka88884b82019-08-27 15:23:07 -0700996 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530997 // BIOS ver
998 std::string biosVer;
Bonnie Loe9baaff2022-11-08 16:36:21 +0800999 if (getBiosVer(biosVer, hostPosition) == 0)
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +05301000 {
1001 frame_info.append("BIOS_FW_ver:", 0);
1002 frame_info.append(biosVer.c_str(), 1);
1003 }
Vijay Khemka88884b82019-08-27 15:23:07 -07001004 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001005
Vijay Khemka317999d2020-01-02 13:43:42 -08001006 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001007 // Board ID
1008
1009 // Battery - Use Escape sequence
1010 frame_info.append("Battery:", 0);
1011 frame_info.append(ESC_BAT " ", 1);
1012 // frame_info.append(&frame_info, esc_bat, 1);
1013
1014 // MCU Version - Use Escape sequence
1015 frame_info.append("MCUbl_ver:", 0);
1016 frame_info.append(ESC_MCU_BL_VER, 1);
1017 frame_info.append("MCU_ver:", 0);
1018 frame_info.append(ESC_MCU_RUN_VER, 1);
1019
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001020 // Sys config present device
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301021 if (hostPosition != BMC_POSITION)
1022 {
1023 frame_info.append("Sys Conf. info:", 0);
1024
1025 // Dimm info
1026 std::vector<std::string> data;
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +05301027 if (sysConfig(data, pos) == 0)
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301028 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +05301029 for (auto& info : data)
1030 {
1031 frame_info.append(info.c_str(), 1);
1032 }
1033 }
1034 else
1035 {
1036 frame_info.append("Not Found", 1);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301037 }
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301038
1039 // Processor info
1040 std::string result;
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +05301041 if (procInfo(result, pos) != 0)
1042 {
1043 result = "Not Found";
1044 }
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +05301045 frame_info.append(result.c_str(), 1);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +05301046 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001047
1048 } // End of update frame
1049
1050 if (page > frame_info.pages)
1051 {
1052 return -1;
1053 }
1054
Vijay Khemka63c99be2020-05-27 19:14:35 -07001055 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001056 if (ret < 0)
1057 {
1058 *count = 0;
1059 return -1;
1060 }
1061 *count = (uint8_t)ret;
1062
1063 if (page < frame_info.pages)
1064 *next = page + 1;
1065 else
1066 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
1067 // last page
1068
1069 return 0;
1070}
1071
Vijay Khemka63c99be2020-05-27 19:14:35 -07001072int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
1073 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001074{
1075 switch (frame)
1076 {
1077 case 1: // info_page
1078 return udbg_get_info_page(frame, page, next, count, buffer);
1079 case 2: // critical SEL
1080 return udbg_get_cri_sel(frame, page, next, count, buffer);
1081 case 3: // critical Sensor
1082 return udbg_get_cri_sensor(frame, page, next, count, buffer);
1083 default:
1084 return -1;
1085 }
1086}
1087
1088static uint8_t panel_main(uint8_t item)
1089{
1090 // Update item list when select item 0
1091 switch (item)
1092 {
1093 case 1:
1094 return panels[PANEL_BOOT_ORDER].select(0);
1095 case 2:
1096 return panels[PANEL_POWER_POLICY].select(0);
1097 default:
1098 return PANEL_MAIN;
1099 }
1100}
1101
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001102static uint8_t panel_boot_order(uint8_t selectedItemIndex)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001103{
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001104 static constexpr size_t sizeBootOrder = 6;
1105 static constexpr size_t bootValid = 0x80;
1106
1107 std::vector<uint8_t> bootSeq;
1108
1109 ctrl_panel& bootOrderPanel = panels[PANEL_BOOT_ORDER];
1110
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301111 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001112
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001113 if (pos == FRU_ALL)
1114 {
1115 bootOrderPanel.item_num = 0;
1116 return PANEL_BOOT_ORDER;
1117 }
1118
1119 auto [bootObjPath, hostName] = ipmi::boot::objPath(pos);
1120 ipmi::boot::getBootOrder(bootObjPath, bootSeq, hostName);
1121
1122 uint8_t& bootMode = bootSeq.front();
1123
1124 // One item is selected to set a new boot sequence.
1125 // The selected item become the first boot order.
1126 if (selectedItemIndex > 0 && selectedItemIndex < sizeBootOrder)
1127 {
1128 // Move the selected item to second element (the first one is boot mode)
1129 std::rotate(bootSeq.begin() + 1, bootSeq.begin() + selectedItemIndex,
1130 bootSeq.begin() + selectedItemIndex + 1);
1131
1132 bootMode |= bootValid;
1133 try
1134 {
1135 ipmi::boot::setBootOrder(bootObjPath, bootSeq, hostName);
1136 }
1137 catch (const std::exception& e)
1138 {
1139 lg2::error("Fail to set boot order : {ERROR}", "ERROR", e);
Willy Tue39f9392022-06-15 13:24:20 -07001140 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001141
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001142 // refresh items
1143 return bootOrderPanel.select(0);
1144 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001145
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001146 // '*': boot flags valid, BIOS has not yet read
1147 bootOrderPanel.item_str[0] = std::string("Boot Order") +
1148 ((bootMode & bootValid) ? "*" : "");
1149
1150 static const std::unordered_map<uint8_t, const char*>
1151 bootOrderMappingTable = {
1152 {0x00, " USB device"}, {0x01, " Network v4"}, {0x02, " SATA HDD"},
1153 {0x03, " SATA-CDROM"}, {0x04, " Other"}, {0x09, " Network v6"},
1154 };
1155
1156 size_t validItem = 0;
1157 for (size_t i = 1; i < sizeBootOrder; i++)
1158 {
1159 auto find = bootOrderMappingTable.find(bootSeq[i]);
1160 if (find == bootOrderMappingTable.end())
Willy Tue39f9392022-06-15 13:24:20 -07001161 {
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001162 lg2::error("Unknown boot order : {BOOTORDER}", "BOOTORDER",
1163 bootSeq[i]);
1164 break;
Willy Tue39f9392022-06-15 13:24:20 -07001165 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001166
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001167 bootOrderPanel.item_str[i] = find->second;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001168
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001169 validItem++;
Willy Tue39f9392022-06-15 13:24:20 -07001170 }
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001171
1172 bootOrderPanel.item_num = validItem;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001173 return PANEL_BOOT_ORDER;
1174}
1175
Willy Tue39f9392022-06-15 13:24:20 -07001176static uint8_t panel_power_policy(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001177{
Willy Tue39f9392022-06-15 13:24:20 -07001178/* To be cleaned */
1179#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001180 uint8_t buff[32] = {0};
1181 uint8_t res_len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301182 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001183 uint8_t policy;
Willy Tue39f9392022-06-15 13:24:20 -07001184 uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1185 POWER_CFG_OFF};
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001186
Willy Tue39f9392022-06-15 13:24:20 -07001187 if (pos != FRU_ALL)
1188 {
1189 if (item > 0 && item <= sizeof(pwr_policy_item_map))
1190 {
1191 policy = pwr_policy_item_map[item - 1];
1192 pal_set_power_restore_policy(pos, &policy, NULL);
1193 }
1194 pal_get_chassis_status(pos, NULL, buff, &res_len);
1195 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1196 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32, "%cPower On",
1197 policy == POWER_CFG_ON ? '*' : ' ');
1198 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32, "%cLast State",
1199 policy == POWER_CFG_LPS ? '*' : ' ');
1200 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32, "%cPower Off",
1201 policy == POWER_CFG_OFF ? '*' : ' ');
1202 panels[PANEL_POWER_POLICY].item_num = 3;
1203 }
1204 else
1205 {
1206 panels[PANEL_POWER_POLICY].item_num = 0;
1207 }
1208#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001209 return PANEL_POWER_POLICY;
1210}
1211
1212int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item,
Vijay Khemka63c99be2020-05-27 19:14:35 -07001213 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001214{
1215 if (panel > panelNum || panel < PANEL_MAIN)
1216 return IPMI_CC_PARM_OUT_OF_RANGE;
1217
1218 // No more item; End of item list
1219 if (item > panels[panel].item_num)
1220 return IPMI_CC_PARM_OUT_OF_RANGE;
1221
1222 switch (operation)
1223 {
1224 case 0: // Get Description
1225 break;
1226 case 1: // Select item
1227 panel = panels[panel].select(item);
1228 item = 0;
1229 break;
1230 case 2: // Back
1231 panel = panels[panel].parent;
1232 item = 0;
1233 break;
1234 default:
1235 return IPMI_CC_PARM_OUT_OF_RANGE;
1236 }
1237
1238 buffer[0] = panel;
1239 buffer[1] = item;
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001240 buffer[2] = std::size(panels[panel].item_str[item]);
1241
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001242 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1243 {
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001244 std::memcpy(&buffer[3], (panels[panel].item_str[item]).c_str(),
1245 buffer[2]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001246 }
1247 *count = buffer[2] + 3;
1248 return IPMI_CC_OK;
1249}
1250
1251} // end of namespace ipmi