| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 1 | /* | 
|  | 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 |  | 
|  | 17 | #include <host-ipmid/ipmid-api.h> | 
| Vijay Khemka | cc0d6d9 | 2019-08-27 14:51:17 -0700 | [diff] [blame] | 18 | #include <nlohmann/json.hpp> | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 19 | #include <stdbool.h> | 
|  | 20 | #include <stdio.h> | 
|  | 21 | #include <sys/stat.h> | 
|  | 22 |  | 
|  | 23 | #include <fstream> | 
|  | 24 | #include <iostream> | 
| Vijay Khemka | cc0d6d9 | 2019-08-27 14:51:17 -0700 | [diff] [blame] | 25 | #include <phosphor-logging/log.hpp> | 
| Vijay Khemka | 88884b8 | 2019-08-27 15:23:07 -0700 | [diff] [blame] | 26 | #include <appcommands.hpp> | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 27 |  | 
|  | 28 | namespace ipmi | 
|  | 29 | { | 
|  | 30 |  | 
| Vijay Khemka | cc0d6d9 | 2019-08-27 14:51:17 -0700 | [diff] [blame] | 31 | #define JSON_POST_DATA_FILE "/usr/share/ipmi-providers/post_desc.json" | 
| Vijay Khemka | 38183d6 | 2019-08-28 16:19:33 -0700 | [diff] [blame] | 32 | #define JSON_GPIO_DATA_FILE "/usr/share/ipmi-providers/gpio_desc.json" | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 33 | #define ETH_INTF_NAME "eth0" | 
|  | 34 |  | 
|  | 35 | #define ESCAPE "\x1B" | 
|  | 36 | #define ESC_BAT ESCAPE "B" | 
|  | 37 | #define ESC_MCU_BL_VER ESCAPE "U" | 
|  | 38 | #define ESC_MCU_RUN_VER ESCAPE "R" | 
|  | 39 | #define ESC_ALT ESCAPE "[5;7m" | 
|  | 40 | #define ESC_RST ESCAPE "[m" | 
|  | 41 |  | 
|  | 42 | #define LINE_DELIMITER '\x1F' | 
|  | 43 |  | 
|  | 44 | #define FRAME_BUFF_SIZE 4096 | 
|  | 45 | #define FRAME_PAGE_BUF_SIZE 256 | 
|  | 46 | #define FRU_ALL 0 | 
|  | 47 | #define MAX_VALUE_LEN 64 | 
|  | 48 |  | 
| Vijay Khemka | 38183d6 | 2019-08-28 16:19:33 -0700 | [diff] [blame] | 49 | #define DEBUG_GPIO_KEY "GpioDesc" | 
|  | 50 | #define GPIO_ARRAY_SIZE 4 | 
|  | 51 | #define GPIO_PIN_INDEX 0 | 
|  | 52 | #define GPIO_LEVEL_INDEX 1 | 
|  | 53 | #define GPIO_DEF_INDEX 2 | 
|  | 54 | #define GPIO_DESC_INDEX 3 | 
|  | 55 |  | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 56 | /* Used for systems which do not specifically have a | 
|  | 57 | * phase, and we want to ignore the phase provided by the | 
|  | 58 | * debug card */ | 
|  | 59 | #define PHASE_ANY 0xff | 
|  | 60 |  | 
|  | 61 | ipmi_ret_t getNetworkData(uint8_t lan_param, char *data); | 
|  | 62 | int8_t getFruData(std::string &serial, std::string &name); | 
|  | 63 |  | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 64 | typedef struct _sensor_desc | 
|  | 65 | { | 
|  | 66 | char name[16]; | 
|  | 67 | uint8_t sensor_num; | 
|  | 68 | char unit[5]; | 
|  | 69 | uint8_t fru; | 
|  | 70 | uint8_t disp_prec; | 
|  | 71 | } sensor_desc_t; | 
|  | 72 |  | 
|  | 73 | struct frame | 
|  | 74 | { | 
|  | 75 | char title[32]; | 
|  | 76 | size_t max_size; | 
|  | 77 | size_t max_page; | 
|  | 78 | char *buf; | 
|  | 79 | uint16_t idx_head, idx_tail; | 
|  | 80 | uint8_t line_per_page; | 
|  | 81 | uint8_t line_width; | 
|  | 82 | uint16_t lines, pages; | 
|  | 83 | uint8_t esc_sts; | 
|  | 84 | uint8_t overwrite; | 
|  | 85 | time_t mtime; | 
|  | 86 | frame() : buf(NULL), pages(0), mtime(0) | 
|  | 87 | { | 
|  | 88 | } | 
|  | 89 | int init(size_t size); | 
|  | 90 | int append(const char *string, int indent); | 
|  | 91 | int insert(const char *string, int indent); | 
|  | 92 | int getPage(int page, char *page_buf, size_t page_buf_size); | 
|  | 93 | int isFull(); | 
|  | 94 | int isEscSeq(char chr); | 
|  | 95 | int parse(char *buf, size_t buf_size, const char *input, int indent); | 
|  | 96 | }; | 
|  | 97 |  | 
|  | 98 | struct frame frame_info; | 
|  | 99 | struct frame frame_sel; | 
|  | 100 | struct frame frame_snr; | 
|  | 101 |  | 
|  | 102 | enum ENUM_PANEL | 
|  | 103 | { | 
|  | 104 | PANEL_MAIN = 1, | 
|  | 105 | PANEL_BOOT_ORDER = 2, | 
|  | 106 | PANEL_POWER_POLICY = 3, | 
|  | 107 | }; | 
|  | 108 |  | 
|  | 109 | struct ctrl_panel | 
|  | 110 | { | 
|  | 111 | uint8_t parent; | 
|  | 112 | uint8_t item_num; | 
|  | 113 | char item_str[8][32]; | 
|  | 114 | uint8_t (*select)(uint8_t item); | 
|  | 115 | }; | 
|  | 116 |  | 
|  | 117 | static uint8_t panel_main(uint8_t item); | 
|  | 118 | static uint8_t panel_boot_order(uint8_t item); | 
|  | 119 | static uint8_t panel_power_policy(uint8_t item); | 
|  | 120 |  | 
|  | 121 | static struct ctrl_panel panels[] = { | 
|  | 122 | {/* dummy entry for making other to 1-based */}, | 
|  | 123 | { | 
|  | 124 | .parent = PANEL_MAIN, | 
|  | 125 | .item_num = 2, | 
|  | 126 | .item_str = | 
|  | 127 | { | 
|  | 128 | "User Setting", | 
|  | 129 | ">Boot Order", | 
|  | 130 | ">Power Policy", | 
|  | 131 | }, | 
|  | 132 | .select = panel_main, | 
|  | 133 | }, | 
|  | 134 | { | 
|  | 135 | .parent = PANEL_MAIN, | 
|  | 136 | .item_num = 0, | 
|  | 137 | .item_str = | 
|  | 138 | { | 
|  | 139 | "Boot Order", | 
|  | 140 | }, | 
|  | 141 | .select = panel_boot_order, | 
|  | 142 | }, | 
|  | 143 | { | 
|  | 144 | .parent = PANEL_MAIN, | 
|  | 145 | .item_num = 0, | 
|  | 146 | .item_str = | 
|  | 147 | { | 
|  | 148 | "Power Policy", | 
|  | 149 | }, | 
|  | 150 | .select = panel_power_policy, | 
|  | 151 | }, | 
|  | 152 | }; | 
|  | 153 |  | 
|  | 154 | static int panelNum = (sizeof(panels) / sizeof(struct ctrl_panel)) - 1; | 
|  | 155 |  | 
|  | 156 | /* Returns the FRU the hand-switch is switched to. If it is switched to BMC | 
|  | 157 | * it returns FRU_ALL. Note, if in err, it returns FRU_ALL */ | 
|  | 158 | static uint8_t plat_get_fru_sel() | 
|  | 159 | { | 
|  | 160 | // For Tiogapass it just return 1, can modify to support more platform | 
|  | 161 | return 1; | 
|  | 162 | } | 
|  | 163 |  | 
|  | 164 | // return 0 on seccuess | 
|  | 165 | int frame::init(size_t size) | 
|  | 166 | { | 
|  | 167 | // Reset status | 
|  | 168 | idx_head = idx_tail = 0; | 
|  | 169 | lines = 0; | 
|  | 170 | esc_sts = 0; | 
|  | 171 | pages = 1; | 
|  | 172 |  | 
|  | 173 | if (buf != NULL && max_size == size) | 
|  | 174 | { | 
|  | 175 | // reinit | 
|  | 176 | return 0; | 
|  | 177 | } | 
|  | 178 |  | 
|  | 179 | if (buf != NULL && max_size != size) | 
|  | 180 | { | 
|  | 181 | delete[] buf; | 
|  | 182 | } | 
|  | 183 | // Initialize Configuration | 
|  | 184 | title[0] = '\0'; | 
|  | 185 | buf = new char[size]; | 
|  | 186 | max_size = size; | 
|  | 187 | max_page = size; | 
|  | 188 | line_per_page = 7; | 
|  | 189 | line_width = 16; | 
|  | 190 | overwrite = 0; | 
|  | 191 |  | 
|  | 192 | if (buf) | 
|  | 193 | return 0; | 
|  | 194 | else | 
|  | 195 | return -1; | 
|  | 196 | } | 
|  | 197 |  | 
|  | 198 | // return 0 on seccuess | 
|  | 199 | int frame::append(const char *string, int indent) | 
|  | 200 | { | 
|  | 201 | const size_t buf_size = 64; | 
|  | 202 | char lbuf[buf_size]; | 
|  | 203 | char *ptr; | 
|  | 204 | int ret; | 
|  | 205 |  | 
|  | 206 | ret = parse(lbuf, buf_size, string, indent); | 
|  | 207 |  | 
|  | 208 | if (ret < 0) | 
|  | 209 | return ret; | 
|  | 210 |  | 
|  | 211 | int len = strlen(string); | 
|  | 212 | for (ptr = lbuf; *ptr != '\0'; ptr++) | 
|  | 213 | { | 
|  | 214 | if (isFull()) | 
|  | 215 | { | 
|  | 216 | if (overwrite) | 
|  | 217 | { | 
|  | 218 | if (buf[idx_head] == LINE_DELIMITER) | 
|  | 219 | lines--; | 
|  | 220 | idx_head = (idx_head + 1) % max_size; | 
|  | 221 | } | 
|  | 222 | else | 
|  | 223 | return -1; | 
|  | 224 | } | 
|  | 225 |  | 
|  | 226 | buf[idx_tail] = *ptr; | 
|  | 227 | if (*ptr == LINE_DELIMITER) | 
|  | 228 | lines++; | 
|  | 229 |  | 
|  | 230 | idx_tail = (idx_tail + 1) % max_size; | 
|  | 231 | } | 
|  | 232 |  | 
|  | 233 | pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0); | 
|  | 234 |  | 
|  | 235 | if (pages > max_page) | 
|  | 236 | pages = max_page; | 
|  | 237 |  | 
|  | 238 | return 0; | 
|  | 239 | } | 
|  | 240 |  | 
|  | 241 | // return 0 on seccuess | 
|  | 242 | int frame::insert(const char *string, int indent) | 
|  | 243 | { | 
|  | 244 | const size_t buf_size = 128; | 
|  | 245 | char lbuf[buf_size]; | 
|  | 246 | char *ptr; | 
|  | 247 | int ret; | 
|  | 248 | int i; | 
|  | 249 |  | 
|  | 250 | ret = parse(lbuf, buf_size, string, indent); | 
|  | 251 |  | 
|  | 252 | if (ret < 0) | 
|  | 253 | return ret; | 
|  | 254 |  | 
|  | 255 | for (i = strlen(lbuf) - 1; i >= 0; i--) | 
|  | 256 | { | 
|  | 257 | ptr = &lbuf[i]; | 
|  | 258 | if (isFull()) | 
|  | 259 | { | 
|  | 260 | if (overwrite) | 
|  | 261 | { | 
|  | 262 | idx_tail = (idx_tail + max_size - 1) % max_size; | 
|  | 263 | if (buf[idx_tail] == LINE_DELIMITER) | 
|  | 264 | lines--; | 
|  | 265 | } | 
|  | 266 | else | 
|  | 267 | return -1; | 
|  | 268 | } | 
|  | 269 |  | 
|  | 270 | idx_head = (idx_head + max_size - 1) % max_size; | 
|  | 271 |  | 
|  | 272 | buf[idx_head] = *ptr; | 
|  | 273 | if (*ptr == LINE_DELIMITER) | 
|  | 274 | lines++; | 
|  | 275 | } | 
|  | 276 |  | 
|  | 277 | pages = (lines / line_per_page) + ((lines % line_per_page) ? 1 : 0); | 
|  | 278 |  | 
|  | 279 | if (pages > max_page) | 
|  | 280 | pages = max_page; | 
|  | 281 |  | 
|  | 282 | return 0; | 
|  | 283 | } | 
|  | 284 |  | 
|  | 285 | // return page size | 
|  | 286 | int frame::getPage(int page, char *page_buf, size_t page_buf_size) | 
|  | 287 | { | 
|  | 288 | int ret; | 
|  | 289 | uint16_t line = 0; | 
|  | 290 | uint16_t idx, len; | 
|  | 291 |  | 
|  | 292 | if (buf == NULL) | 
|  | 293 | return -1; | 
|  | 294 |  | 
|  | 295 | // 1-based page | 
|  | 296 | if (page > pages || page < 1) | 
|  | 297 | return -1; | 
|  | 298 |  | 
|  | 299 | if (page_buf == NULL || page_buf_size < 0) | 
|  | 300 | return -1; | 
|  | 301 |  | 
|  | 302 | ret = snprintf(page_buf, 17, "%-10s %02d/%02d", title, page, pages); | 
|  | 303 | len = strlen(page_buf); | 
|  | 304 | if (ret < 0) | 
|  | 305 | return -1; | 
|  | 306 |  | 
|  | 307 | line = 0; | 
|  | 308 | idx = idx_head; | 
|  | 309 | while (line < ((page - 1) * line_per_page) && idx != idx_tail) | 
|  | 310 | { | 
|  | 311 | if (buf[idx] == LINE_DELIMITER) | 
|  | 312 | line++; | 
|  | 313 | idx = (idx + 1) % max_size; | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | while (line < ((page)*line_per_page) && idx != idx_tail) | 
|  | 317 | { | 
|  | 318 | if (buf[idx] == LINE_DELIMITER) | 
|  | 319 | { | 
|  | 320 | line++; | 
|  | 321 | } | 
|  | 322 | else | 
|  | 323 | { | 
|  | 324 | page_buf[len++] = buf[idx]; | 
|  | 325 | if (len == (page_buf_size - 1)) | 
|  | 326 | { | 
|  | 327 | break; | 
|  | 328 | } | 
|  | 329 | } | 
|  | 330 | idx = (idx + 1) % max_size; | 
|  | 331 | } | 
|  | 332 |  | 
|  | 333 | return len; | 
|  | 334 | } | 
|  | 335 |  | 
|  | 336 | // return 1 for frame buffer full | 
|  | 337 | int frame::isFull() | 
|  | 338 | { | 
|  | 339 | if (buf == NULL) | 
|  | 340 | return -1; | 
|  | 341 |  | 
|  | 342 | if ((idx_tail + 1) % max_size == idx_head) | 
|  | 343 | return 1; | 
|  | 344 | else | 
|  | 345 | return 0; | 
|  | 346 | } | 
|  | 347 |  | 
|  | 348 | // return 1 for Escape Sequence | 
|  | 349 | int frame::isEscSeq(char chr) | 
|  | 350 | { | 
|  | 351 | uint8_t curr_sts = esc_sts; | 
|  | 352 |  | 
|  | 353 | if (esc_sts == 0 && (chr == 0x1b)) | 
|  | 354 | esc_sts = 1; // Escape Sequence | 
|  | 355 | else if (esc_sts == 1 && (chr == 0x5b)) | 
|  | 356 | esc_sts = 2; // Control Sequence Introducer(CSI) | 
|  | 357 | else if (esc_sts == 1 && (chr != 0x5b)) | 
|  | 358 | esc_sts = 0; | 
|  | 359 | else if (esc_sts == 2 && (chr >= 0x40 && chr <= 0x7e)) | 
|  | 360 | esc_sts = 0; | 
|  | 361 |  | 
|  | 362 | if (curr_sts || esc_sts) | 
|  | 363 | return 1; | 
|  | 364 | else | 
|  | 365 | return 0; | 
|  | 366 | } | 
|  | 367 |  | 
|  | 368 | // return 0 on success | 
|  | 369 | int frame::parse(char *lbuf, size_t buf_size, const char *input, int indent) | 
|  | 370 | { | 
|  | 371 | uint8_t pos, esc; | 
|  | 372 | int i; | 
|  | 373 | const char *in, *end; | 
|  | 374 |  | 
|  | 375 | if (buf == NULL || input == NULL) | 
|  | 376 | return -1; | 
|  | 377 |  | 
|  | 378 | if (indent >= line_width || indent < 0) | 
|  | 379 | return -1; | 
|  | 380 |  | 
|  | 381 | in = input; | 
|  | 382 | end = in + strlen(input); | 
|  | 383 | pos = 0; // line position | 
|  | 384 | esc = 0; // escape state | 
|  | 385 | i = 0;   // buf index | 
|  | 386 | while (in != end) | 
|  | 387 | { | 
|  | 388 | if (i >= buf_size) | 
|  | 389 | break; | 
|  | 390 |  | 
|  | 391 | if (pos < indent) | 
|  | 392 | { | 
|  | 393 | // fill indent | 
|  | 394 | lbuf[i++] = ' '; | 
|  | 395 | pos++; | 
|  | 396 | continue; | 
|  | 397 | } | 
|  | 398 |  | 
|  | 399 | esc = isEscSeq(*in); | 
|  | 400 |  | 
|  | 401 | if (!esc && pos == line_width) | 
|  | 402 | { | 
|  | 403 | lbuf[i++] = LINE_DELIMITER; | 
|  | 404 | pos = 0; | 
|  | 405 | continue; | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | if (!esc) | 
|  | 409 | pos++; | 
|  | 410 |  | 
|  | 411 | // fill input data | 
|  | 412 | lbuf[i++] = *(in++); | 
|  | 413 | } | 
|  | 414 |  | 
|  | 415 | // padding | 
|  | 416 | while (pos <= line_width) | 
|  | 417 | { | 
|  | 418 | if (i >= buf_size) | 
|  | 419 | break; | 
|  | 420 | if (pos < line_width) | 
|  | 421 | lbuf[i++] = ' '; | 
|  | 422 | else | 
|  | 423 | lbuf[i++] = LINE_DELIMITER; | 
|  | 424 | pos++; | 
|  | 425 | } | 
|  | 426 |  | 
|  | 427 | // full | 
|  | 428 | if (i >= buf_size) | 
|  | 429 | return -1; | 
|  | 430 |  | 
|  | 431 | lbuf[i++] = '\0'; | 
|  | 432 |  | 
|  | 433 | return 0; | 
|  | 434 | } | 
|  | 435 |  | 
|  | 436 | static int chk_cri_sel_update(uint8_t *cri_sel_up) | 
|  | 437 | { | 
|  | 438 | FILE *fp; | 
|  | 439 | struct stat file_stat; | 
|  | 440 | uint8_t pos = plat_get_fru_sel(); | 
|  | 441 | static uint8_t pre_pos = 0xff; | 
|  | 442 |  | 
|  | 443 | fp = fopen("/mnt/data/cri_sel", "r"); | 
|  | 444 | if (fp) | 
|  | 445 | { | 
|  | 446 | if ((stat("/mnt/data/cri_sel", &file_stat) == 0) && | 
|  | 447 | (file_stat.st_mtime != frame_sel.mtime || pre_pos != pos)) | 
|  | 448 | { | 
|  | 449 | *cri_sel_up = 1; | 
|  | 450 | } | 
|  | 451 | else | 
|  | 452 | { | 
|  | 453 | *cri_sel_up = 0; | 
|  | 454 | } | 
|  | 455 | fclose(fp); | 
|  | 456 | } | 
|  | 457 | else | 
|  | 458 | { | 
|  | 459 | if (frame_sel.buf == NULL || frame_sel.lines != 0 || pre_pos != pos) | 
|  | 460 | { | 
|  | 461 | *cri_sel_up = 1; | 
|  | 462 | } | 
|  | 463 | else | 
|  | 464 | { | 
|  | 465 | *cri_sel_up = 0; | 
|  | 466 | } | 
|  | 467 | } | 
|  | 468 | pre_pos = pos; | 
|  | 469 | return 0; | 
|  | 470 | } | 
|  | 471 |  | 
|  | 472 | int plat_udbg_get_frame_info(uint8_t *num) | 
|  | 473 | { | 
|  | 474 | *num = 3; | 
|  | 475 | return 0; | 
|  | 476 | } | 
|  | 477 |  | 
|  | 478 | int plat_udbg_get_updated_frames(uint8_t *count, uint8_t *buffer) | 
|  | 479 | { | 
|  | 480 | uint8_t cri_sel_up = 0; | 
|  | 481 | uint8_t info_page_up = 1; | 
|  | 482 |  | 
|  | 483 | *count = 0; | 
|  | 484 |  | 
|  | 485 | // info page update | 
|  | 486 | if (info_page_up == 1) | 
|  | 487 | { | 
|  | 488 | buffer[*count] = 1; | 
|  | 489 | *count += 1; | 
|  | 490 | } | 
|  | 491 |  | 
|  | 492 | // cri sel update | 
|  | 493 | chk_cri_sel_update(&cri_sel_up); | 
|  | 494 | if (cri_sel_up == 1) | 
|  | 495 | { | 
|  | 496 | buffer[*count] = 2; | 
|  | 497 | *count += 1; | 
|  | 498 | } | 
|  | 499 |  | 
|  | 500 | // cri sensor update | 
|  | 501 | buffer[*count] = 3; | 
|  | 502 | *count += 1; | 
|  | 503 |  | 
|  | 504 | return 0; | 
|  | 505 | } | 
|  | 506 |  | 
|  | 507 | int plat_udbg_get_post_desc(uint8_t index, uint8_t *next, uint8_t phase, | 
|  | 508 | uint8_t *end, uint8_t *length, uint8_t *buffer) | 
|  | 509 | { | 
| Vijay Khemka | cc0d6d9 | 2019-08-27 14:51:17 -0700 | [diff] [blame] | 510 | nlohmann::json postObj; | 
|  | 511 | std::string postCode; | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 512 |  | 
| Vijay Khemka | cc0d6d9 | 2019-08-27 14:51:17 -0700 | [diff] [blame] | 513 | /* Get post description data stored in json file */ | 
|  | 514 | std::ifstream file(JSON_POST_DATA_FILE); | 
|  | 515 | if (file) | 
|  | 516 | { | 
|  | 517 | file >> postObj; | 
|  | 518 | file.close(); | 
|  | 519 | } | 
|  | 520 | else | 
|  | 521 | { | 
|  | 522 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 523 | "Post code description file not found", | 
|  | 524 | phosphor::logging::entry("POST_CODE_FILE=%s", JSON_POST_DATA_FILE)); | 
|  | 525 | return -1; | 
|  | 526 | } | 
|  | 527 |  | 
|  | 528 | std::string phaseStr = "PhaseAny"; | 
|  | 529 | if (postObj.find(phaseStr) == postObj.end()) | 
|  | 530 | { | 
|  | 531 | phaseStr = "Phase" + std::to_string(phase); | 
|  | 532 | } | 
|  | 533 |  | 
|  | 534 | if (postObj.find(phaseStr) == postObj.end()) | 
|  | 535 | { | 
|  | 536 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 537 | "Post code phase not available", | 
|  | 538 | phosphor::logging::entry("PHASE=%d", phase)); | 
|  | 539 | return -1; | 
|  | 540 | } | 
|  | 541 |  | 
|  | 542 | auto phaseObj = postObj[phaseStr]; | 
|  | 543 | int phaseSize = phaseObj.size(); | 
|  | 544 |  | 
|  | 545 | for (int i = 0; i < phaseSize; i++) | 
|  | 546 | { | 
|  | 547 | postCode = phaseObj[i][0]; | 
|  | 548 | if (index == stoul(postCode, nullptr, 16)) | 
|  | 549 | { | 
|  | 550 | std::string postDesc = phaseObj[i][1]; | 
|  | 551 | *length = postDesc.size(); | 
|  | 552 | memcpy(buffer, postDesc.data(), *length); | 
|  | 553 | buffer[*length] = '\0'; | 
|  | 554 |  | 
|  | 555 | if (phaseSize != i + 1) | 
|  | 556 | { | 
|  | 557 | postCode = phaseObj[i + 1][0]; | 
|  | 558 | *next = stoul(postCode, nullptr, 16); | 
|  | 559 | *end = 0; | 
|  | 560 | } | 
|  | 561 | else | 
|  | 562 | { | 
|  | 563 | if (postObj.size() != phase) | 
|  | 564 | { | 
|  | 565 | std::string nextPhaseStr = | 
|  | 566 | "Phase" + std::to_string(phase + 1); | 
|  | 567 | postCode = postObj[nextPhaseStr][0][0]; | 
|  | 568 | *next = stoul(postCode, nullptr, 16); | 
|  | 569 | *end = 0; | 
|  | 570 | } | 
|  | 571 | else | 
|  | 572 | { | 
|  | 573 | *next = 0xff; | 
|  | 574 | *end = 1; | 
|  | 575 | } | 
|  | 576 | } | 
|  | 577 |  | 
|  | 578 | return 0; | 
|  | 579 | } | 
|  | 580 | } | 
|  | 581 |  | 
|  | 582 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 583 | "Post code description data not available", | 
|  | 584 | phosphor::logging::entry("PHASE_CODE=%d_0x%x", phase, index)); | 
|  | 585 | return -1; | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 586 | } | 
|  | 587 |  | 
|  | 588 | /* Need to implement this */ | 
|  | 589 | int plat_udbg_get_gpio_desc(uint8_t index, uint8_t *next, uint8_t *level, | 
| Vijay Khemka | 38183d6 | 2019-08-28 16:19:33 -0700 | [diff] [blame] | 590 | uint8_t *def, uint8_t *length, uint8_t *buffer) | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 591 | { | 
| Vijay Khemka | 38183d6 | 2019-08-28 16:19:33 -0700 | [diff] [blame] | 592 | nlohmann::json gpioObj; | 
|  | 593 | std::string gpioPin; | 
|  | 594 |  | 
|  | 595 | /* Get gpio data stored in json file */ | 
|  | 596 | std::ifstream file(JSON_GPIO_DATA_FILE); | 
|  | 597 | if (file) | 
|  | 598 | { | 
|  | 599 | file >> gpioObj; | 
|  | 600 | file.close(); | 
|  | 601 | } | 
|  | 602 | else | 
|  | 603 | { | 
|  | 604 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 605 | "GPIO pin description file not found", | 
|  | 606 | phosphor::logging::entry("GPIO_PIN_DETAILS_FILE=%s", | 
|  | 607 | JSON_GPIO_DATA_FILE)); | 
|  | 608 | return -1; | 
|  | 609 | } | 
|  | 610 |  | 
|  | 611 | if (gpioObj.find(DEBUG_GPIO_KEY) == gpioObj.end()) | 
|  | 612 | { | 
|  | 613 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 614 | "GPIO pin details not available", | 
|  | 615 | phosphor::logging::entry("GPIO_JSON_KEY=%d", DEBUG_GPIO_KEY)); | 
|  | 616 | return -1; | 
|  | 617 | } | 
|  | 618 |  | 
|  | 619 | auto obj = gpioObj[DEBUG_GPIO_KEY]; | 
|  | 620 | int objSize = obj.size(); | 
|  | 621 |  | 
|  | 622 | for (int i = 0; i < objSize; i++) | 
|  | 623 | { | 
|  | 624 | if (obj[i].size() != GPIO_ARRAY_SIZE) | 
|  | 625 | { | 
|  | 626 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 627 | "Size of gpio array is incorrect", | 
|  | 628 | phosphor::logging::entry("EXPECTED_SIZE=%d", GPIO_ARRAY_SIZE)); | 
|  | 629 | return -1; | 
|  | 630 | } | 
|  | 631 |  | 
|  | 632 | gpioPin = obj[i][GPIO_PIN_INDEX]; | 
|  | 633 | if (index == stoul(gpioPin, nullptr, 16)) | 
|  | 634 | { | 
|  | 635 | if (objSize != i + 1) | 
|  | 636 | { | 
|  | 637 | gpioPin = obj[i + 1][GPIO_PIN_INDEX]; | 
|  | 638 | *next = stoul(gpioPin, nullptr, 16); | 
|  | 639 | } | 
|  | 640 | else | 
|  | 641 | { | 
|  | 642 | *next = 0xff; | 
|  | 643 | } | 
|  | 644 |  | 
|  | 645 | *level = obj[i][GPIO_LEVEL_INDEX]; | 
|  | 646 | *def = obj[i][GPIO_DEF_INDEX]; | 
|  | 647 | std::string gpioDesc = obj[i][GPIO_DESC_INDEX]; | 
|  | 648 | *length = gpioDesc.size(); | 
|  | 649 | memcpy(buffer, gpioDesc.data(), *length); | 
|  | 650 | buffer[*length] = '\0'; | 
|  | 651 |  | 
|  | 652 | return 0; | 
|  | 653 | } | 
|  | 654 | } | 
|  | 655 |  | 
|  | 656 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 657 | "GPIO pin description data not available", | 
|  | 658 | phosphor::logging::entry("GPIO_PIN=0x%x", index)); | 
|  | 659 | return -1; | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 660 | } | 
|  | 661 |  | 
|  | 662 | static int udbg_get_cri_sel(uint8_t frame, uint8_t page, uint8_t *next, | 
|  | 663 | uint8_t *count, uint8_t *buffer) | 
|  | 664 | { | 
|  | 665 | int len; | 
|  | 666 | int ret; | 
|  | 667 | char line_buff[FRAME_PAGE_BUF_SIZE], *fptr; | 
|  | 668 | const char *ptr; | 
|  | 669 | FILE *fp; | 
|  | 670 | struct stat file_stat; | 
|  | 671 | uint8_t pos = plat_get_fru_sel(); | 
|  | 672 | static uint8_t pre_pos = FRU_ALL; | 
|  | 673 | bool pos_changed = pre_pos != pos; | 
|  | 674 |  | 
|  | 675 | pre_pos = pos; | 
|  | 676 |  | 
|  | 677 | /* Revisit this */ | 
|  | 678 | fp = fopen("/mnt/data/cri_sel", "r"); | 
|  | 679 | if (fp) | 
|  | 680 | { | 
|  | 681 | if ((stat("/mnt/data/cri_sel", &file_stat) == 0) && | 
|  | 682 | (file_stat.st_mtime != frame_sel.mtime || pos_changed)) | 
|  | 683 | { | 
|  | 684 | // initialize and clear frame | 
|  | 685 | frame_sel.init(FRAME_BUFF_SIZE); | 
|  | 686 | frame_sel.overwrite = 1; | 
|  | 687 | frame_sel.max_page = 20; | 
|  | 688 | frame_sel.mtime = file_stat.st_mtime; | 
|  | 689 | snprintf(frame_sel.title, 32, "Cri SEL"); | 
|  | 690 |  | 
|  | 691 | while (fgets(line_buff, FRAME_PAGE_BUF_SIZE, fp)) | 
|  | 692 | { | 
|  | 693 | // Remove newline | 
|  | 694 | line_buff[strlen(line_buff) - 1] = '\0'; | 
|  | 695 | ptr = line_buff; | 
|  | 696 | // Find message | 
|  | 697 | ptr = strstr(ptr, "local0.err"); | 
|  | 698 | if (ptr == NULL) | 
|  | 699 | { | 
|  | 700 | continue; | 
|  | 701 | } | 
|  | 702 |  | 
|  | 703 | if ((ptr = strrchr(ptr, ':')) == NULL) | 
|  | 704 | { | 
|  | 705 | continue; | 
|  | 706 | } | 
|  | 707 | len = strlen(ptr); | 
|  | 708 | if (len > 2) | 
|  | 709 | { | 
|  | 710 | // to skip log string ": " | 
|  | 711 | ptr += 2; | 
|  | 712 | } | 
|  | 713 | // Write new message | 
|  | 714 | frame_sel.insert(ptr, 0); | 
|  | 715 | } | 
|  | 716 | } | 
|  | 717 | fclose(fp); | 
|  | 718 | } | 
|  | 719 | else | 
|  | 720 | { | 
|  | 721 | // Title only | 
|  | 722 | frame_sel.init(FRAME_BUFF_SIZE); | 
|  | 723 | snprintf(frame_sel.title, 32, "Cri SEL"); | 
|  | 724 | frame_sel.mtime = 0; | 
|  | 725 | } | 
|  | 726 |  | 
|  | 727 | if (page > frame_sel.pages) | 
|  | 728 | { | 
|  | 729 | return -1; | 
|  | 730 | } | 
|  | 731 |  | 
|  | 732 | ret = frame_sel.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE); | 
|  | 733 | if (ret < 0) | 
|  | 734 | { | 
|  | 735 | *count = 0; | 
|  | 736 | return -1; | 
|  | 737 | } | 
|  | 738 | *count = (uint8_t)ret; | 
|  | 739 |  | 
|  | 740 | if (page < frame_sel.pages) | 
|  | 741 | *next = page + 1; | 
|  | 742 | else | 
|  | 743 | *next = 0xFF; // Set the value of next to 0xFF to indicate this is the | 
|  | 744 | // last page | 
|  | 745 |  | 
|  | 746 | return 0; | 
|  | 747 | } | 
|  | 748 |  | 
|  | 749 | static int udbg_get_cri_sensor(uint8_t frame, uint8_t page, uint8_t *next, | 
|  | 750 | uint8_t *count, uint8_t *buffer) | 
|  | 751 | { | 
|  | 752 | char str[32], temp_val[16], temp_thresh[8], print_format[32]; | 
|  | 753 | int i, ret; | 
|  | 754 | float fvalue; | 
|  | 755 | sensor_desc_t *cri_sensor = NULL; | 
|  | 756 | size_t sensor_count = 0; | 
|  | 757 | uint8_t pos = plat_get_fru_sel(); | 
|  | 758 | uint8_t fru; | 
|  | 759 |  | 
|  | 760 | if (page == 1) | 
|  | 761 | { | 
|  | 762 | // Only update frame data while getting page 1 | 
|  | 763 |  | 
|  | 764 | // initialize and clear frame | 
|  | 765 | frame_snr.init(FRAME_BUFF_SIZE); | 
|  | 766 | snprintf(frame_snr.title, 32, "CriSensor"); | 
|  | 767 | frame_snr.append(str, 0); | 
|  | 768 | } // End of update frame | 
|  | 769 |  | 
|  | 770 | if (page > frame_snr.pages) | 
|  | 771 | { | 
|  | 772 | return -1; | 
|  | 773 | } | 
|  | 774 |  | 
|  | 775 | ret = frame_snr.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE); | 
|  | 776 | if (ret < 0) | 
|  | 777 | { | 
|  | 778 | *count = 0; | 
|  | 779 | return -1; | 
|  | 780 | } | 
|  | 781 | *count = (uint8_t)ret; | 
|  | 782 |  | 
|  | 783 | if (page < frame_snr.pages) | 
|  | 784 | *next = page + 1; | 
|  | 785 | else | 
|  | 786 | *next = 0xFF; // Set the value of next to 0xFF to indicate this is the | 
|  | 787 | // last page | 
|  | 788 |  | 
|  | 789 | return 0; | 
|  | 790 | } | 
|  | 791 |  | 
| Vijay Khemka | 88884b8 | 2019-08-27 15:23:07 -0700 | [diff] [blame] | 792 | static int getBiosVer(std::string &ver) | 
|  | 793 | { | 
|  | 794 | nlohmann::json appObj; | 
|  | 795 |  | 
|  | 796 | std::ifstream file(JSON_APP_DATA_FILE); | 
|  | 797 | if (file) | 
|  | 798 | { | 
|  | 799 | file >> appObj; | 
|  | 800 | file.close(); | 
|  | 801 | if (appObj.find(KEY_SYSFW_VER) != appObj.end()) | 
|  | 802 | { | 
|  | 803 | ver = appObj[KEY_SYSFW_VER].get<std::string>(); | 
|  | 804 | return 0; | 
|  | 805 | } | 
|  | 806 | } | 
|  | 807 |  | 
|  | 808 | return -1; | 
|  | 809 | } | 
|  | 810 |  | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 811 | static int udbg_get_info_page(uint8_t frame, uint8_t page, uint8_t *next, | 
|  | 812 | uint8_t *count, uint8_t *buffer) | 
|  | 813 | { | 
|  | 814 | char line_buff[1000], *pres_dev = line_buff; | 
|  | 815 | uint8_t pos = plat_get_fru_sel(); | 
|  | 816 | const char *delim = "\n"; | 
|  | 817 | int ret; | 
|  | 818 | std::string serialName = "BOARD_SERIAL_NUMBER"; | 
|  | 819 | std::string partName = "BOARD_PART_NUMBER"; | 
|  | 820 | std::string verDel = "VERSION="; | 
|  | 821 | std::string verPath = "/etc/os-release"; | 
|  | 822 |  | 
|  | 823 | if (page == 1) | 
|  | 824 | { | 
|  | 825 | // Only update frame data while getting page 1 | 
|  | 826 |  | 
|  | 827 | // initialize and clear frame | 
|  | 828 | frame_info.init(FRAME_BUFF_SIZE); | 
|  | 829 | snprintf(frame_info.title, 32, "SYS_Info"); | 
|  | 830 |  | 
|  | 831 | // FRU TBD: | 
|  | 832 | std::string data; | 
|  | 833 | frame_info.append("SN:", 0); | 
|  | 834 | if (getFruData(data, serialName) != 0) | 
|  | 835 | { | 
|  | 836 | data = "Not Found"; | 
|  | 837 | } | 
|  | 838 | frame_info.append(data.c_str(), 1); | 
|  | 839 | frame_info.append("PN:", 0); | 
|  | 840 | if (getFruData(data, partName) != 0) | 
|  | 841 | { | 
|  | 842 | data = "Not Found"; | 
|  | 843 | } | 
|  | 844 | frame_info.append(data.c_str(), 1); | 
|  | 845 |  | 
|  | 846 | // LAN | 
|  | 847 | getNetworkData(3, line_buff); | 
|  | 848 | frame_info.append("BMC_IP:", 0); | 
|  | 849 | frame_info.append(line_buff, 1); | 
|  | 850 | getNetworkData(59, line_buff); | 
|  | 851 | frame_info.append("BMC_IPv6:", 0); | 
|  | 852 | frame_info.append(line_buff, 1); | 
|  | 853 |  | 
|  | 854 | // BMC ver | 
|  | 855 | std::ifstream file(verPath); | 
|  | 856 | if (file) | 
|  | 857 | { | 
|  | 858 | std::string line; | 
|  | 859 | while (std::getline(file, line)) | 
|  | 860 | { | 
|  | 861 | if (line.find(verDel) != std::string::npos) | 
|  | 862 | { | 
|  | 863 | std::string bmcVer = line.substr(verDel.size()); | 
|  | 864 | frame_info.append("BMC_FW_ver:", 0); | 
|  | 865 | frame_info.append(bmcVer.c_str(), 1); | 
|  | 866 | break; | 
|  | 867 | } | 
|  | 868 | } | 
|  | 869 | } | 
|  | 870 |  | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 871 | // BIOS ver | 
| Vijay Khemka | 88884b8 | 2019-08-27 15:23:07 -0700 | [diff] [blame] | 872 | std::string biosVer; | 
|  | 873 | if (getBiosVer(biosVer) == 0) | 
|  | 874 | { | 
|  | 875 | frame_info.append("BIOS_FW_ver:", 0); | 
|  | 876 | frame_info.append(biosVer.c_str(), 1); | 
|  | 877 | } | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 878 |  | 
| Vijay Khemka | 88884b8 | 2019-08-27 15:23:07 -0700 | [diff] [blame] | 879 | /* TBD: ME status and Board ID needs implementation */ | 
| Vijay Khemka | e7d23d0 | 2019-03-08 13:13:40 -0800 | [diff] [blame] | 880 | // ME status | 
|  | 881 |  | 
|  | 882 | // Board ID | 
|  | 883 |  | 
|  | 884 | // Battery - Use Escape sequence | 
|  | 885 | frame_info.append("Battery:", 0); | 
|  | 886 | frame_info.append(ESC_BAT "     ", 1); | 
|  | 887 | // frame_info.append(&frame_info, esc_bat, 1); | 
|  | 888 |  | 
|  | 889 | // MCU Version - Use Escape sequence | 
|  | 890 | frame_info.append("MCUbl_ver:", 0); | 
|  | 891 | frame_info.append(ESC_MCU_BL_VER, 1); | 
|  | 892 | frame_info.append("MCU_ver:", 0); | 
|  | 893 | frame_info.append(ESC_MCU_RUN_VER, 1); | 
|  | 894 |  | 
|  | 895 | // TBD: | 
|  | 896 | // Sys config present device | 
|  | 897 |  | 
|  | 898 | } // End of update frame | 
|  | 899 |  | 
|  | 900 | if (page > frame_info.pages) | 
|  | 901 | { | 
|  | 902 | return -1; | 
|  | 903 | } | 
|  | 904 |  | 
|  | 905 | ret = frame_info.getPage(page, (char *)buffer, FRAME_PAGE_BUF_SIZE); | 
|  | 906 | if (ret < 0) | 
|  | 907 | { | 
|  | 908 | *count = 0; | 
|  | 909 | return -1; | 
|  | 910 | } | 
|  | 911 | *count = (uint8_t)ret; | 
|  | 912 |  | 
|  | 913 | if (page < frame_info.pages) | 
|  | 914 | *next = page + 1; | 
|  | 915 | else | 
|  | 916 | *next = 0xFF; // Set the value of next to 0xFF to indicate this is the | 
|  | 917 | // last page | 
|  | 918 |  | 
|  | 919 | return 0; | 
|  | 920 | } | 
|  | 921 |  | 
|  | 922 | int plat_udbg_get_frame_data(uint8_t frame, uint8_t page, uint8_t *next, | 
|  | 923 | uint8_t *count, uint8_t *buffer) | 
|  | 924 | { | 
|  | 925 | switch (frame) | 
|  | 926 | { | 
|  | 927 | case 1: // info_page | 
|  | 928 | return udbg_get_info_page(frame, page, next, count, buffer); | 
|  | 929 | case 2: // critical SEL | 
|  | 930 | return udbg_get_cri_sel(frame, page, next, count, buffer); | 
|  | 931 | case 3: // critical Sensor | 
|  | 932 | return udbg_get_cri_sensor(frame, page, next, count, buffer); | 
|  | 933 | default: | 
|  | 934 | return -1; | 
|  | 935 | } | 
|  | 936 | } | 
|  | 937 |  | 
|  | 938 | static uint8_t panel_main(uint8_t item) | 
|  | 939 | { | 
|  | 940 | // Update item list when select item 0 | 
|  | 941 | switch (item) | 
|  | 942 | { | 
|  | 943 | case 1: | 
|  | 944 | return panels[PANEL_BOOT_ORDER].select(0); | 
|  | 945 | case 2: | 
|  | 946 | return panels[PANEL_POWER_POLICY].select(0); | 
|  | 947 | default: | 
|  | 948 | return PANEL_MAIN; | 
|  | 949 | } | 
|  | 950 | } | 
|  | 951 |  | 
|  | 952 | static uint8_t panel_boot_order(uint8_t item) | 
|  | 953 | { | 
|  | 954 | int i; | 
|  | 955 | unsigned char buff[MAX_VALUE_LEN], pickup, len; | 
|  | 956 | uint8_t pos = plat_get_fru_sel(); | 
|  | 957 |  | 
|  | 958 | /* To be implemented */ | 
|  | 959 | /* | 
|  | 960 | if (pos != FRU_ALL && pal_get_boot_order(pos, buff, buff, &len) == 0) | 
|  | 961 | { | 
|  | 962 | if (item > 0 && item < SIZE_BOOT_ORDER) | 
|  | 963 | { | 
|  | 964 | pickup = buff[item]; | 
|  | 965 | while (item > 1) | 
|  | 966 | { | 
|  | 967 | buff[item] = buff[item -1]; | 
|  | 968 | item--; | 
|  | 969 | } | 
|  | 970 | buff[item] = pickup; | 
|  | 971 | buff[0] |= 0x80; | 
|  | 972 | pal_set_boot_order(pos, buff, buff, &len); | 
|  | 973 |  | 
|  | 974 | // refresh items | 
|  | 975 | return panels[PANEL_BOOT_ORDER].select(0); | 
|  | 976 | } | 
|  | 977 |  | 
|  | 978 | // '*': boot flags valid, BIOS has not yet read | 
|  | 979 | snprintf(panels[PANEL_BOOT_ORDER].item_str[0], 32, | 
|  | 980 | "Boot Order%c", (buff[0] & 0x80)?'*':'\0'); | 
|  | 981 |  | 
|  | 982 | for (i = 1; i < SIZE_BOOT_ORDER; i++) | 
|  | 983 | { | 
|  | 984 | switch (buff[i]) | 
|  | 985 | { | 
|  | 986 | case 0x0: | 
|  | 987 | snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32, | 
|  | 988 | " USB device"); | 
|  | 989 | break; | 
|  | 990 | case 0x1: | 
|  | 991 | snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32, | 
|  | 992 | " Network v4"); | 
|  | 993 | break; | 
|  | 994 | case (0x1 | 0x8): | 
|  | 995 | snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32, | 
|  | 996 | " Network v6"); | 
|  | 997 | break; | 
|  | 998 | case 0x2: | 
|  | 999 | snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32, | 
|  | 1000 | " SATA HDD"); | 
|  | 1001 | break; | 
|  | 1002 | case 0x3: | 
|  | 1003 | snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32, | 
|  | 1004 | " SATA-CDROM"); | 
|  | 1005 | break; | 
|  | 1006 | case 0x4: | 
|  | 1007 | snprintf(panels[PANEL_BOOT_ORDER].item_str[i], 32, | 
|  | 1008 | " Other"); | 
|  | 1009 | break; | 
|  | 1010 | default: | 
|  | 1011 | panels[PANEL_BOOT_ORDER].item_str[i][0] = '\0'; | 
|  | 1012 | break; | 
|  | 1013 | } | 
|  | 1014 | } | 
|  | 1015 |  | 
|  | 1016 | // remove empty items | 
|  | 1017 | for (i--; (strlen(panels[PANEL_BOOT_ORDER].item_str[i]) == 0) && (i > 0); i--) | 
|  | 1018 | ; | 
|  | 1019 |  | 
|  | 1020 | panels[PANEL_BOOT_ORDER].item_num = i; | 
|  | 1021 | } else | 
|  | 1022 | { | 
|  | 1023 | panels[PANEL_BOOT_ORDER].item_num = 0; | 
|  | 1024 | } | 
|  | 1025 | */ | 
|  | 1026 | return PANEL_BOOT_ORDER; | 
|  | 1027 | } | 
|  | 1028 |  | 
|  | 1029 | static uint8_t panel_power_policy(uint8_t item) | 
|  | 1030 | { | 
|  | 1031 | uint8_t buff[32] = {0}; | 
|  | 1032 | uint8_t res_len; | 
|  | 1033 | uint8_t pos = plat_get_fru_sel(); | 
|  | 1034 | uint8_t policy; | 
|  | 1035 | //  uint8_t pwr_policy_item_map[3] = {POWER_CFG_ON, POWER_CFG_LPS, | 
|  | 1036 | //  POWER_CFG_OFF}; | 
|  | 1037 |  | 
|  | 1038 | /* To be cleaned */ | 
|  | 1039 | /* | 
|  | 1040 | if (pos != FRU_ALL) { | 
|  | 1041 | if (item > 0 && item <= sizeof(pwr_policy_item_map)) { | 
|  | 1042 | policy = pwr_policy_item_map[item - 1]; | 
|  | 1043 | pal_set_power_restore_policy(pos, &policy, NULL); | 
|  | 1044 | } | 
|  | 1045 | pal_get_chassis_status(pos, NULL, buff, &res_len); | 
|  | 1046 | policy = (((uint8_t)buff[0]) >> 5) & 0x7; | 
|  | 1047 | snprintf(panels[PANEL_POWER_POLICY].item_str[1], 32, | 
|  | 1048 | "%cPower On", policy == POWER_CFG_ON ? '*' : ' '); | 
|  | 1049 | snprintf(panels[PANEL_POWER_POLICY].item_str[2], 32, | 
|  | 1050 | "%cLast State", policy == POWER_CFG_LPS ? '*' : ' '); | 
|  | 1051 | snprintf(panels[PANEL_POWER_POLICY].item_str[3], 32, | 
|  | 1052 | "%cPower Off", policy == POWER_CFG_OFF ? '*' : ' '); | 
|  | 1053 | panels[PANEL_POWER_POLICY].item_num = 3; | 
|  | 1054 | } else { | 
|  | 1055 | panels[PANEL_POWER_POLICY].item_num = 0; | 
|  | 1056 | } | 
|  | 1057 | */ | 
|  | 1058 | return PANEL_POWER_POLICY; | 
|  | 1059 | } | 
|  | 1060 |  | 
|  | 1061 | int plat_udbg_control_panel(uint8_t panel, uint8_t operation, uint8_t item, | 
|  | 1062 | uint8_t *count, uint8_t *buffer) | 
|  | 1063 | { | 
|  | 1064 | if (panel > panelNum || panel < PANEL_MAIN) | 
|  | 1065 | return IPMI_CC_PARM_OUT_OF_RANGE; | 
|  | 1066 |  | 
|  | 1067 | // No more item; End of item list | 
|  | 1068 | if (item > panels[panel].item_num) | 
|  | 1069 | return IPMI_CC_PARM_OUT_OF_RANGE; | 
|  | 1070 |  | 
|  | 1071 | switch (operation) | 
|  | 1072 | { | 
|  | 1073 | case 0: // Get Description | 
|  | 1074 | break; | 
|  | 1075 | case 1: // Select item | 
|  | 1076 | panel = panels[panel].select(item); | 
|  | 1077 | item = 0; | 
|  | 1078 | break; | 
|  | 1079 | case 2: // Back | 
|  | 1080 | panel = panels[panel].parent; | 
|  | 1081 | item = 0; | 
|  | 1082 | break; | 
|  | 1083 | default: | 
|  | 1084 | return IPMI_CC_PARM_OUT_OF_RANGE; | 
|  | 1085 | } | 
|  | 1086 |  | 
|  | 1087 | buffer[0] = panel; | 
|  | 1088 | buffer[1] = item; | 
|  | 1089 | buffer[2] = strlen(panels[panel].item_str[item]); | 
|  | 1090 | if (buffer[2] > 0 && (buffer[2] + 3) < FRAME_PAGE_BUF_SIZE) | 
|  | 1091 | { | 
|  | 1092 | memcpy(&buffer[3], panels[panel].item_str[item], buffer[2]); | 
|  | 1093 | } | 
|  | 1094 | *count = buffer[2] + 3; | 
|  | 1095 | return IPMI_CC_OK; | 
|  | 1096 | } | 
|  | 1097 |  | 
|  | 1098 | } // end of namespace ipmi |