Johnny Lin | 3acea5c | 2021-01-08 15:24:25 +0800 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
| 2 | |
| 3 | #include <console/console.h> |
Sergii Dmytruk | ef7dd5d | 2021-10-22 01:02:32 +0300 | [diff] [blame] | 4 | #include <drivers/ipmi/ipmi_if.h> |
Johnny Lin | 3acea5c | 2021-01-08 15:24:25 +0800 | [diff] [blame] | 5 | |
| 6 | #include "ipmi_ocp.h" |
| 7 | |
| 8 | enum cb_err ipmi_set_post_start(const int port) |
| 9 | { |
| 10 | int ret; |
| 11 | struct ipmi_rsp rsp; |
| 12 | |
Sergii Dmytruk | ef7dd5d | 2021-10-22 01:02:32 +0300 | [diff] [blame] | 13 | ret = ipmi_message(port, IPMI_NETFN_OEM, 0x0, |
Elyes Haouas | 1ef547e | 2022-11-18 15:05:39 +0100 | [diff] [blame^] | 14 | IPMI_BMC_SET_POST_START, NULL, 0, (u8 *)&rsp, |
Sergii Dmytruk | ef7dd5d | 2021-10-22 01:02:32 +0300 | [diff] [blame] | 15 | sizeof(rsp)); |
Johnny Lin | 3acea5c | 2021-01-08 15:24:25 +0800 | [diff] [blame] | 16 | |
| 17 | if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) { |
| 18 | printk(BIOS_ERR, "IPMI: %s command failed (ret=%d rsp=0x%x)\n", |
| 19 | __func__, ret, rsp.completion_code); |
| 20 | return CB_ERR; |
| 21 | } |
| 22 | if (ret != sizeof(rsp)) { |
| 23 | printk(BIOS_ERR, "IPMI: %s response truncated\n", __func__); |
| 24 | return CB_ERR; |
| 25 | } |
| 26 | |
| 27 | printk(BIOS_DEBUG, "IPMI BMC POST is started\n"); |
| 28 | return CB_SUCCESS; |
| 29 | } |
| 30 | |
| 31 | enum cb_err ipmi_set_cmos_clear(void) |
| 32 | { |
| 33 | int ret; |
| 34 | |
| 35 | struct ipmi_oem_rsp { |
| 36 | struct ipmi_rsp resp; |
| 37 | struct boot_order data; |
| 38 | } __packed; |
| 39 | |
| 40 | struct ipmi_oem_rsp rsp; |
| 41 | struct boot_order req; |
| 42 | |
| 43 | /* IPMI OEM get bios boot order command to check if the valid bit and |
| 44 | the CMOS clear bit are both set from the response BootMode byte. */ |
Sergii Dmytruk | ef7dd5d | 2021-10-22 01:02:32 +0300 | [diff] [blame] | 45 | ret = ipmi_message(CONFIG_BMC_KCS_BASE, IPMI_NETFN_OEM, 0x0, |
| 46 | IPMI_OEM_GET_BIOS_BOOT_ORDER, |
| 47 | NULL, 0, |
Elyes Haouas | 1ef547e | 2022-11-18 15:05:39 +0100 | [diff] [blame^] | 48 | (unsigned char *)&rsp, sizeof(rsp)); |
Johnny Lin | 3acea5c | 2021-01-08 15:24:25 +0800 | [diff] [blame] | 49 | |
| 50 | if (ret < sizeof(struct ipmi_rsp) || rsp.resp.completion_code) { |
| 51 | printk(BIOS_ERR, "IPMI: %s command failed (read ret=%d resp=0x%x)\n", |
| 52 | __func__, ret, rsp.resp.completion_code); |
| 53 | return CB_ERR; |
| 54 | } |
| 55 | |
| 56 | if (!IS_CMOS_AND_VALID_BIT(rsp.data.boot_mode)) { |
| 57 | req = rsp.data; |
| 58 | SET_CMOS_AND_VALID_BIT(req.boot_mode); |
Sergii Dmytruk | ef7dd5d | 2021-10-22 01:02:32 +0300 | [diff] [blame] | 59 | ret = ipmi_message(CONFIG_BMC_KCS_BASE, IPMI_NETFN_OEM, 0x0, |
| 60 | IPMI_OEM_SET_BIOS_BOOT_ORDER, |
Elyes Haouas | 1ef547e | 2022-11-18 15:05:39 +0100 | [diff] [blame^] | 61 | (const unsigned char *)&req, sizeof(req), |
| 62 | (unsigned char *)&rsp, sizeof(rsp)); |
Johnny Lin | 3acea5c | 2021-01-08 15:24:25 +0800 | [diff] [blame] | 63 | |
| 64 | if (ret < sizeof(struct ipmi_rsp) || rsp.resp.completion_code) { |
| 65 | printk(BIOS_ERR, "IPMI: %s command failed (sent ret=%d resp=0x%x)\n", |
| 66 | __func__, ret, rsp.resp.completion_code); |
| 67 | return CB_ERR; |
| 68 | } |
| 69 | |
| 70 | printk(BIOS_INFO, "IPMI CMOS clear requested because CMOS data is invalid.\n"); |
| 71 | |
| 72 | return CB_SUCCESS; |
| 73 | } |
| 74 | |
| 75 | return CB_SUCCESS; |
| 76 | } |