blob: d47a0a1dae66b79842095e747cdc596aa0b66cdb [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 Williams010dee02024-08-16 15:19:44 -040060 std::string service =
61 getService(*dbus, ipmi::selector::interface, ipmi::selector::path);
62 Value variant =
63 getDbusProperty(*dbus, service, ipmi::selector::path,
64 ipmi::selector::interface, "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 Williams010dee02024-08-16 15:19:44 -040080 std::string service =
81 getService(*dbus, ipmi::selector::interface, 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 Williams010dee02024-08-16 15:19:44 -0400519 std::string nextPhaseStr =
520 "Phase" + 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
Bonnie Loe9baaff2022-11-08 16:36:21 +0800615static int getBiosVer(std::string& ver, size_t hostPosition)
Vijay Khemka88884b82019-08-27 15:23:07 -0700616{
617 nlohmann::json appObj;
618
619 std::ifstream file(JSON_APP_DATA_FILE);
620 if (file)
621 {
622 file >> appObj;
623 file.close();
Bonnie Loe9baaff2022-11-08 16:36:21 +0800624 std::string version_key = KEY_SYSFW_VER + std::to_string(hostPosition);
625
626 if (appObj.find(version_key) != appObj.end())
Vijay Khemka88884b82019-08-27 15:23:07 -0700627 {
Bonnie Loe9baaff2022-11-08 16:36:21 +0800628 ver = appObj[version_key].get<std::string>();
Vijay Khemka88884b82019-08-27 15:23:07 -0700629 return 0;
630 }
631 }
632
633 return -1;
634}
635
Manikandan Elumalai5f8e3432020-12-02 03:46:55 +0530636int sendBicCmd(uint8_t netFn, uint8_t cmd, uint8_t bicAddr,
637 std::vector<uint8_t>& cmdData, std::vector<uint8_t>& respData)
638{
639 static constexpr uint8_t lun = 0;
640
641 auto bus = getSdBus();
642
643 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
644 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
645 "org.openbmc.Ipmb", "sendRequest");
646 method.append(bicAddr, netFn, lun, cmd, cmdData);
647
648 auto reply = bus->call(method);
649 if (reply.is_method_error())
650 {
651 phosphor::logging::log<phosphor::logging::level::ERR>(
652 "Error reading from BIC");
653 return -1;
654 }
655
656 IpmbMethodType resp;
657 reply.read(resp);
658
659 respData =
660 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
661
662 return 0;
663}
664
Vijay Khemka63c99be2020-05-27 19:14:35 -0700665int sendMeCmd(uint8_t netFn, uint8_t cmd, std::vector<uint8_t>& cmdData,
666 std::vector<uint8_t>& respData)
Vijay Khemkadd14c0f2020-03-18 14:48:13 -0700667{
668 auto bus = getSdBus();
669
670 if (DEBUG)
671 {
672 std::cout << "ME NetFn:cmd " << (int)netFn << ":" << (int)cmd << "\n";
673 std::cout << "ME req data: ";
674 for (auto d : cmdData)
675 {
676 std::cout << d << " ";
677 }
678 std::cout << "\n";
679 }
680
681 auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
682 "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
683 "org.openbmc.Ipmb", "sendRequest");
684 method.append(meAddress, netFn, lun, cmd, cmdData);
685
686 auto reply = bus->call(method);
687 if (reply.is_method_error())
688 {
689 phosphor::logging::log<phosphor::logging::level::ERR>(
690 "Error reading from ME");
691 return -1;
692 }
693
694 IpmbMethodType resp;
695 reply.read(resp);
696
697 respData =
698 std::move(std::get<std::remove_reference_t<decltype(respData)>>(resp));
699
700 if (DEBUG)
701 {
702 std::cout << "ME resp data: ";
703 for (auto d : respData)
704 {
705 std::cout << d << " ";
706 }
707 std::cout << "\n";
708 }
709
710 return 0;
711}
712
Willy Tue39f9392022-06-15 13:24:20 -0700713static int udbg_get_info_page(uint8_t, uint8_t page, uint8_t* next,
Vijay Khemka63c99be2020-05-27 19:14:35 -0700714 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800715{
Willy Tue39f9392022-06-15 13:24:20 -0700716 char line_buff[1000];
717 [[maybe_unused]] char* pres_dev = line_buff;
718 [[maybe_unused]] size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800719 int ret;
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530720 std::string serialName = "SerialNumber";
721 std::string partName = "PartNumber";
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800722 std::string verDel = "VERSION=";
723 std::string verPath = "/etc/os-release";
BonnieLo-wiwynn21a79232023-03-09 16:42:48 +0800724 size_t hostPosition = 0;
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530725 size_t maxPosition;
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800726
727 if (page == 1)
728 {
729 // Only update frame data while getting page 1
730
731 // initialize and clear frame
732 frame_info.init(FRAME_BUFF_SIZE);
733 snprintf(frame_info.title, 32, "SYS_Info");
734
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530735 bool platform = isMultiHostPlatform();
736 if (platform == true)
737 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530738 hostPosition = plat_get_fru_sel();
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530739 }
740
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530741 getMaxHostPosition(maxPosition);
Jayashree Dhanapal4ec80562022-06-28 15:41:47 +0530742 if (hostPosition == BMC_POSITION || hostInstances == "0")
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530743 {
744 frame_info.append("FRU:spb", 0);
745 }
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530746 else if (hostPosition != BMC_POSITION && hostPosition <= maxPosition)
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530747 {
748 std::string data = "FRU:slot" + std::to_string(hostPosition);
749 frame_info.append(data.c_str(), 0);
750 }
751
752 // FRU
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800753 std::string data;
754 frame_info.append("SN:", 0);
755 if (getFruData(data, serialName) != 0)
756 {
757 data = "Not Found";
758 }
759 frame_info.append(data.c_str(), 1);
760 frame_info.append("PN:", 0);
761 if (getFruData(data, partName) != 0)
762 {
763 data = "Not Found";
764 }
765 frame_info.append(data.c_str(), 1);
766
767 // LAN
768 getNetworkData(3, line_buff);
769 frame_info.append("BMC_IP:", 0);
770 frame_info.append(line_buff, 1);
771 getNetworkData(59, line_buff);
772 frame_info.append("BMC_IPv6:", 0);
773 frame_info.append(line_buff, 1);
774
775 // BMC ver
776 std::ifstream file(verPath);
777 if (file)
778 {
779 std::string line;
780 while (std::getline(file, line))
781 {
782 if (line.find(verDel) != std::string::npos)
783 {
784 std::string bmcVer = line.substr(verDel.size());
785 frame_info.append("BMC_FW_ver:", 0);
786 frame_info.append(bmcVer.c_str(), 1);
787 break;
788 }
789 }
790 }
791
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530792 if (hostPosition != BMC_POSITION)
Vijay Khemka88884b82019-08-27 15:23:07 -0700793 {
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530794 // BIOS ver
795 std::string biosVer;
Bonnie Loe9baaff2022-11-08 16:36:21 +0800796 if (getBiosVer(biosVer, hostPosition) == 0)
Karthikeyan Pasupathi98aabdb2022-04-06 17:18:51 +0530797 {
798 frame_info.append("BIOS_FW_ver:", 0);
799 frame_info.append(biosVer.c_str(), 1);
800 }
Vijay Khemka88884b82019-08-27 15:23:07 -0700801 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800802
Vijay Khemka317999d2020-01-02 13:43:42 -0800803 /* TBD: Board ID needs implementation */
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800804 // Board ID
805
806 // Battery - Use Escape sequence
807 frame_info.append("Battery:", 0);
808 frame_info.append(ESC_BAT " ", 1);
809 // frame_info.append(&frame_info, esc_bat, 1);
810
811 // MCU Version - Use Escape sequence
812 frame_info.append("MCUbl_ver:", 0);
813 frame_info.append(ESC_MCU_BL_VER, 1);
814 frame_info.append("MCU_ver:", 0);
815 frame_info.append(ESC_MCU_RUN_VER, 1);
816
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800817 // Sys config present device
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530818 if (hostPosition != BMC_POSITION)
819 {
820 frame_info.append("Sys Conf. info:", 0);
821
822 // Dimm info
823 std::vector<std::string> data;
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530824 if (sysConfig(data, pos) == 0)
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530825 {
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530826 for (auto& info : data)
827 {
828 frame_info.append(info.c_str(), 1);
829 }
830 }
831 else
832 {
833 frame_info.append("Not Found", 1);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530834 }
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +0530835
836 // Processor info
837 std::string result;
Karthikeyan Pasupathie1ff81f2022-11-21 17:54:46 +0530838 if (procInfo(result, pos) != 0)
839 {
840 result = "Not Found";
841 }
Karthikeyan Pasupathid532fec2022-07-14 14:43:42 +0530842 frame_info.append(result.c_str(), 1);
Karthikeyan Pasupathi10ff3d82022-04-06 16:27:25 +0530843 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800844
845 } // End of update frame
846
847 if (page > frame_info.pages)
848 {
849 return -1;
850 }
851
Vijay Khemka63c99be2020-05-27 19:14:35 -0700852 ret = frame_info.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800853 if (ret < 0)
854 {
855 *count = 0;
856 return -1;
857 }
858 *count = (uint8_t)ret;
859
860 if (page < frame_info.pages)
861 *next = page + 1;
862 else
863 *next = 0xFF; // Set the value of next to 0xFF to indicate this is the
864 // last page
865
866 return 0;
867}
868
Peter Yinb340aa22024-07-08 16:07:55 +0800869static int udbg_get_postcode(uint8_t, uint8_t page, uint8_t* next,
870 uint8_t* count, uint8_t* buffer)
871{
872 if (page == 1)
873 {
874 // Initialize and clear frame (example initialization)
875 frame_postcode.init(FRAME_BUFF_SIZE);
876 snprintf(frame_postcode.title, 32, "Extra Post Code");
877 frame_sel.overwrite = 1;
878 frame_sel.max_page = 5;
879
880 // Synchronously get D-Bus connection
881 auto bus = sdbusplus::bus::new_default();
882
883 // Build D-Bus method call
884 auto method = bus.new_method_call(
885 "xyz.openbmc_project.State.Boot.PostCode0", // Target service name
886 "/xyz/openbmc_project/State/Boot/PostCode0", // Object path
887 "xyz.openbmc_project.State.Boot.PostCode", // Interface name
888 "GetPostCodes"); // Method name
889
890 method.append(uint16_t(1)); // Add method parameter, assuming it's page
891
892 try
893 {
894 auto reply = bus.call(method); // Send synchronous method call
895
896 // Read postcode value
897 std::vector<std::tuple<uint64_t, std::vector<uint8_t>>> postcodes;
898 reply.read(postcodes);
899
900 // Insert retrieved postcodes into frame_postcode
901 std::string result;
902 for (const auto& [code, extra] : postcodes)
903 {
904 result = std::format("{:02x}", code);
905 frame_postcode.append(result.c_str(), 0);
906 }
907 }
908 catch (const std::exception& e)
909 {
910 // Handle exceptions
911 std::cerr << "Error retrieving postcodes: " << e.what()
912 << std::endl;
913 return -1;
914 }
915 }
916
917 if (page > frame_postcode.pages)
918 {
919 return -1;
920 }
921
922 int ret = frame_postcode.getPage(page, (char*)buffer, FRAME_PAGE_BUF_SIZE);
923 if (ret < 0)
924 {
925 *count = 0;
926 return -1;
927 }
928 *count = (uint8_t)ret;
929
930 if (page < frame_postcode.pages)
931 *next = page + 1;
932 else
933 *next = 0xFF; // Set next to 0xFF to indicate last page
934 return 0;
935}
936
Vijay Khemka63c99be2020-05-27 19:14:35 -0700937int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t* next,
938 uint8_t* count, uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800939{
940 switch (frame)
941 {
942 case 1: // info_page
943 return udbg_get_info_page(frame, page, next, count, buffer);
Peter Yinb340aa22024-07-08 16:07:55 +0800944 case 2: // Extra Post Code
945 return udbg_get_postcode(frame, page, next, count, buffer);
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800946 default:
947 return -1;
948 }
949}
950
951static uint8_t panel_main(uint8_t item)
952{
953 // Update item list when select item 0
954 switch (item)
955 {
956 case 1:
957 return panels[PANEL_BOOT_ORDER].select(0);
958 case 2:
959 return panels[PANEL_POWER_POLICY].select(0);
960 default:
961 return PANEL_MAIN;
962 }
963}
964
Delphine CC Chiu7bb45922023-04-10 13:34:04 +0800965static uint8_t panel_boot_order(uint8_t selectedItemIndex)
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800966{
Delphine CC Chiu7bb45922023-04-10 13:34:04 +0800967 static constexpr size_t sizeBootOrder = 6;
968 static constexpr size_t bootValid = 0x80;
969
970 std::vector<uint8_t> bootSeq;
971
972 ctrl_panel& bootOrderPanel = panels[PANEL_BOOT_ORDER];
973
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +0530974 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -0800975
Delphine CC Chiu7bb45922023-04-10 13:34:04 +0800976 if (pos == FRU_ALL)
977 {
978 bootOrderPanel.item_num = 0;
979 return PANEL_BOOT_ORDER;
980 }
981
982 auto [bootObjPath, hostName] = ipmi::boot::objPath(pos);
983 ipmi::boot::getBootOrder(bootObjPath, bootSeq, hostName);
984
985 uint8_t& bootMode = bootSeq.front();
986
987 // One item is selected to set a new boot sequence.
988 // The selected item become the first boot order.
989 if (selectedItemIndex > 0 && selectedItemIndex < sizeBootOrder)
990 {
991 // Move the selected item to second element (the first one is boot mode)
992 std::rotate(bootSeq.begin() + 1, bootSeq.begin() + selectedItemIndex,
993 bootSeq.begin() + selectedItemIndex + 1);
994
995 bootMode |= bootValid;
996 try
997 {
998 ipmi::boot::setBootOrder(bootObjPath, bootSeq, hostName);
999 }
1000 catch (const std::exception& e)
1001 {
1002 lg2::error("Fail to set boot order : {ERROR}", "ERROR", e);
Willy Tue39f9392022-06-15 13:24:20 -07001003 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001004
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001005 // refresh items
1006 return bootOrderPanel.select(0);
1007 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001008
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001009 // '*': boot flags valid, BIOS has not yet read
Patrick Williams010dee02024-08-16 15:19:44 -04001010 bootOrderPanel.item_str[0] =
1011 std::string("Boot Order") + ((bootMode & bootValid) ? "*" : "");
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001012
1013 static const std::unordered_map<uint8_t, const char*>
1014 bootOrderMappingTable = {
1015 {0x00, " USB device"}, {0x01, " Network v4"}, {0x02, " SATA HDD"},
1016 {0x03, " SATA-CDROM"}, {0x04, " Other"}, {0x09, " Network v6"},
1017 };
1018
1019 size_t validItem = 0;
1020 for (size_t i = 1; i < sizeBootOrder; i++)
1021 {
1022 auto find = bootOrderMappingTable.find(bootSeq[i]);
1023 if (find == bootOrderMappingTable.end())
Willy Tue39f9392022-06-15 13:24:20 -07001024 {
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001025 lg2::error("Unknown boot order : {BOOTORDER}", "BOOTORDER",
1026 bootSeq[i]);
1027 break;
Willy Tue39f9392022-06-15 13:24:20 -07001028 }
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001029
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001030 bootOrderPanel.item_str[i] = find->second;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001031
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001032 validItem++;
Willy Tue39f9392022-06-15 13:24:20 -07001033 }
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001034
1035 bootOrderPanel.item_num = validItem;
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001036 return PANEL_BOOT_ORDER;
1037}
1038
Willy Tue39f9392022-06-15 13:24:20 -07001039static uint8_t panel_power_policy(uint8_t)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001040{
Willy Tue39f9392022-06-15 13:24:20 -07001041/* To be cleaned */
1042#if 0
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001043 uint8_t buff[32] = {0};
1044 uint8_t res_len;
Karthikeyan Pasupathi39836ff2022-01-17 12:20:06 +05301045 size_t pos = plat_get_fru_sel();
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001046 uint8_t policy;
Willy Tue39f9392022-06-15 13:24:20 -07001047 uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS,
1048 POWER_CFG_OFF};
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001049
Willy Tue39f9392022-06-15 13:24:20 -07001050 if (pos != FRU_ALL)
1051 {
1052 if (item > 0 && item <= sizeof(pwr_policy_item_map))
1053 {
1054 policy = pwr_policy_item_map[item - 1];
1055 pal_set_power_restore_policy(pos, &policy, NULL);
1056 }
1057 pal_get_chassis_status(pos, NULL, buff, &res_len);
1058 policy = (((uint8_t)buff[0]) >> 5) & 0x7;
1059 snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32, "%cPower On",
1060 policy == POWER_CFG_ON ? '*' : ' ');
1061 snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32, "%cLast State",
1062 policy == POWER_CFG_LPS ? '*' : ' ');
1063 snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32, "%cPower Off",
1064 policy == POWER_CFG_OFF ? '*' : ' ');
1065 panels[PANEL_POWER_POLICY].item_num = 3;
1066 }
1067 else
1068 {
1069 panels[PANEL_POWER_POLICY].item_num = 0;
1070 }
1071#endif
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001072 return PANEL_POWER_POLICY;
1073}
1074
Patrick Williams5e589482024-07-13 16:18:13 -05001075ipmi_ret_t plat_udbg_control_panel(uint8_t panel, uint8_t operation,
1076 uint8_t item, uint8_t* count,
1077 uint8_t* buffer)
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001078{
1079 if (panel > panelNum || panel < PANEL_MAIN)
1080 return IPMI_CC_PARM_OUT_OF_RANGE;
1081
1082 // No more item; End of item list
1083 if (item > panels[panel].item_num)
1084 return IPMI_CC_PARM_OUT_OF_RANGE;
1085
1086 switch (operation)
1087 {
1088 case 0: // Get Description
1089 break;
1090 case 1: // Select item
1091 panel = panels[panel].select(item);
1092 item = 0;
1093 break;
1094 case 2: // Back
1095 panel = panels[panel].parent;
1096 item = 0;
1097 break;
1098 default:
1099 return IPMI_CC_PARM_OUT_OF_RANGE;
1100 }
1101
1102 buffer[0] = panel;
1103 buffer[1] = item;
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001104 buffer[2] = std::size(panels[panel].item_str[item]);
1105
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001106 if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE)
1107 {
Delphine CC Chiu7bb45922023-04-10 13:34:04 +08001108 std::memcpy(&buffer[3], (panels[panel].item_str[item]).c_str(),
1109 buffer[2]);
Vijay Khemkae7d23d02019-03-08 13:13:40 -08001110 }
1111 *count = buffer[2] + 3;
1112 return IPMI_CC_OK;
1113}
1114
1115} // end of namespace ipmi