xref: /aosp_15_r20/external/coreboot/src/drivers/ipmi/ipmi_if.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include "ipmi_if.h"
4 
5 #include <console/console.h>
6 #include <delay.h>
7 
8 #include "chip.h"
9 
ipmi_get_device_id(const struct device * dev,struct ipmi_devid_rsp * rsp)10 int ipmi_get_device_id(const struct device *dev, struct ipmi_devid_rsp *rsp)
11 {
12 	int ret;
13 
14 	ret = ipmi_message(dev->path.pnp.port, IPMI_NETFN_APPLICATION, 0,
15 			   IPMI_BMC_GET_DEVICE_ID, NULL, 0, (u8 *)rsp,
16 			   sizeof(*rsp));
17 	if (ret < sizeof(struct ipmi_rsp) || rsp->resp.completion_code) {
18 		printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n",
19 		       __func__, ret, rsp->resp.completion_code);
20 		return 1;
21 	}
22 	if (ret != sizeof(*rsp)) {
23 		printk(BIOS_ERR, "IPMI: %s response truncated\n", __func__);
24 		return 1;
25 	}
26 	return 0;
27 }
28 
ipmi_get_bmc_self_test_result(const struct device * dev,struct ipmi_selftest_rsp * rsp)29 static int ipmi_get_bmc_self_test_result(const struct device *dev,
30 					 struct ipmi_selftest_rsp *rsp)
31 {
32 	int ret;
33 
34 	ret = ipmi_message(dev->path.pnp.port, IPMI_NETFN_APPLICATION, 0,
35 			   IPMI_BMC_GET_SELFTEST_RESULTS, NULL, 0, (u8 *)rsp,
36 			   sizeof(*rsp));
37 
38 	if (ret < sizeof(struct ipmi_rsp) || rsp->resp.completion_code) {
39 		printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n",
40 		       __func__, ret, rsp->resp.completion_code);
41 		return 1;
42 	}
43 	if (ret != sizeof(*rsp)) {
44 		printk(BIOS_ERR, "IPMI: %s response truncated\n", __func__);
45 		return 1;
46 	}
47 
48 	return 0;
49 }
50 
ipmi_process_self_test_result(const struct device * dev)51 int ipmi_process_self_test_result(const struct device *dev)
52 {
53 	int failure = 0;
54 	uint8_t retry_count = 0;
55 	struct ipmi_selftest_rsp selftestrsp = {0};
56 
57 	const struct drivers_ipmi_config *conf = dev->chip_info;
58 	uint8_t retry_limit = 0;
59 
60 	if (conf && conf->wait_for_bmc)
61 		retry_limit = conf->bmc_boot_timeout;
62 
63 	if (retry_limit == 0)
64 		/* Try to get self-test results at least once */
65 		retry_limit = 1;
66 
67 	printk(BIOS_INFO, "Get BMC self test result...");
68 	for (retry_count = 0; retry_count < retry_limit; retry_count++) {
69 		if (!ipmi_get_bmc_self_test_result(dev, &selftestrsp))
70 			break;
71 
72 		mdelay(1000);
73 	}
74 
75 	switch (selftestrsp.result) {
76 	case IPMI_APP_SELFTEST_NO_ERROR: /* 0x55 */
77 		printk(BIOS_DEBUG, "No Error\n");
78 		break;
79 	case IPMI_APP_SELFTEST_NOT_IMPLEMENTED: /* 0x56 */
80 		printk(BIOS_DEBUG, "Function Not Implemented\n");
81 		break;
82 	case IPMI_APP_SELFTEST_ERROR: /* 0x57 */
83 		printk(BIOS_ERR, "BMC: Corrupted or inaccessible data or device\n");
84 		failure = 1;
85 		break;
86 	case IPMI_APP_SELFTEST_FATAL_HW_ERROR: /* 0x58 */
87 		printk(BIOS_ERR, "BMC: Fatal Hardware Error\n");
88 		failure = 1;
89 		break;
90 	case IPMI_APP_SELFTEST_RESERVED: /* 0xFF */
91 		printk(BIOS_DEBUG, "Reserved\n");
92 		break;
93 
94 	default: /* Other Device Specific Hardware Error */
95 		printk(BIOS_ERR, "BMC: Device Specific Error: 0x%02x\n", selftestrsp.result);
96 		failure = 1;
97 		break;
98 	}
99 
100 	return failure;
101 }
102