ipmi_ops.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <console/console.h> 4 #include "ipmi_ops.h" 5 #include "ipmi_if.h" 6 #include <string.h> 7 #include <types.h> 8 9 enum cb_err ipmi_init_and_start_bmc_wdt(const int port, uint16_t countdown, 10 uint8_t action) 11 { 12 int ret; 13 struct ipmi_wdt_req req = {0}; 14 struct ipmi_rsp rsp; 15 printk(BIOS_INFO, "Initializing IPMI BMC watchdog timer\n"); 16 /* BIOS FRB2 */ 17 req.timer_use = 1; 18 req.timer_actions = action; 19 /* clear BIOS FRB2 expiration flag */ 20 req.timer_use_expiration_flags_clr = 2; 21 req.initial_countdown_val = countdown; 22 ret = ipmi_message(port, IPMI_NETFN_APPLICATION, 0x0, 23 IPMI_BMC_SET_WDG_TIMER, 24 (const unsigned char *)&req, sizeof(req), 25 (unsigned char *)&rsp, sizeof(rsp)); 26 27 if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) { 28 printk(BIOS_ERR, "IPMI: %s set wdt command failed " 29 "(ret=%d resp=0x%x), failed to initialize and start " 30 "IPMI BMC watchdog timer\n", __func__, 31 ret, rsp.completion_code); 32 return CB_ERR; 33 } 34 35 /* Reset command to start timer */ 36 ret = ipmi_message(port, IPMI_NETFN_APPLICATION, 0x0, 37 IPMI_BMC_RESET_WDG_TIMER, NULL, 0, 38 (unsigned char *)&rsp, sizeof(rsp)); 39 40 if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) { 41 printk(BIOS_ERR, "IPMI: %s reset wdt command failed " 42 "(ret=%d resp=0x%x), failed to initialize and start " 43 "IPMI BMC watchdog timer\n", __func__, 44 ret, rsp.completion_code); 45 return CB_ERR; 46 } 47 48 printk(BIOS_INFO, "IPMI BMC watchdog initialized and started.\n"); 49 return CB_SUCCESS; 50 } 51 52 enum cb_err ipmi_stop_bmc_wdt(const int port) 53 { 54 int ret; 55 struct ipmi_wdt_req req; 56 struct ipmi_wdt_rsp rsp = {0}; 57 struct ipmi_rsp resp; 58 59 /* Get current timer first */ 60 ret = ipmi_message(port, IPMI_NETFN_APPLICATION, 0x0, 61 IPMI_BMC_GET_WDG_TIMER, NULL, 0, 62 (unsigned char *)&rsp, sizeof(rsp)); 63 64 if (ret < sizeof(struct ipmi_rsp) || rsp.resp.completion_code) { 65 printk(BIOS_ERR, "IPMI: %s get wdt command failed " 66 "(ret=%d resp=0x%x), IPMI BMC watchdog timer may still " 67 "be running\n", __func__, ret, 68 rsp.resp.completion_code); 69 return CB_ERR; 70 } 71 /* If bit 6 in timer_use is 0 then it's already stopped. */ 72 if (!(rsp.data.timer_use & (1 << 6))) { 73 printk(BIOS_DEBUG, "IPMI BMC watchdog is already stopped\n"); 74 return CB_SUCCESS; 75 } 76 /* Set timer stop running by clearing bit 6. */ 77 rsp.data.timer_use &= ~(1 << 6); 78 rsp.data.initial_countdown_val = 0; 79 req = rsp.data; 80 ret = ipmi_message(port, IPMI_NETFN_APPLICATION, 0x0, 81 IPMI_BMC_SET_WDG_TIMER, 82 (const unsigned char *)&req, sizeof(req), 83 (unsigned char *)&resp, sizeof(resp)); 84 85 if (ret < sizeof(struct ipmi_rsp) || resp.completion_code) { 86 printk(BIOS_ERR, "IPMI: %s set wdt command stop timer failed " 87 "(ret=%d resp=0x%x), failed to stop IPMI " 88 "BMC watchdog timer\n", __func__, ret, 89 resp.completion_code); 90 return CB_ERR; 91 } 92 printk(BIOS_DEBUG, "IPMI BMC watchdog is stopped\n"); 93 94 return CB_SUCCESS; 95 } 96 97 enum cb_err ipmi_get_system_guid(const int port, uint8_t *uuid) 98 { 99 int ret; 100 struct ipmi_get_system_guid_rsp rsp; 101 102 if (uuid == NULL) { 103 printk(BIOS_ERR, "%s failed, null pointer parameter\n", 104 __func__); 105 return CB_ERR; 106 } 107 108 ret = ipmi_message(port, IPMI_NETFN_APPLICATION, 0x0, 109 IPMI_BMC_GET_SYSTEM_GUID, NULL, 0, 110 (unsigned char *)&rsp, sizeof(rsp)); 111 112 if (ret < sizeof(struct ipmi_rsp) || rsp.resp.completion_code) { 113 printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n", 114 __func__, ret, rsp.resp.completion_code); 115 return CB_ERR; 116 } 117 118 memcpy(uuid, rsp.data, 16); 119 return CB_SUCCESS; 120 } 121 122 enum cb_err ipmi_add_sel(const int port, struct sel_event_record *sel) 123 { 124 int ret; 125 struct ipmi_add_sel_rsp rsp; 126 127 if (sel == NULL) { 128 printk(BIOS_ERR, "%s failed, system event log is not present.\n", __func__); 129 return CB_ERR; 130 } 131 132 ret = ipmi_message(port, IPMI_NETFN_STORAGE, 0x0, 133 IPMI_ADD_SEL_ENTRY, (const unsigned char *)sel, 134 16, (unsigned char *)&rsp, sizeof(rsp)); 135 136 if (ret < sizeof(struct ipmi_rsp) || rsp.resp.completion_code) { 137 printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n", 138 __func__, ret, rsp.resp.completion_code); 139 return CB_ERR; 140 } 141 return CB_SUCCESS; 142 }