coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
ipmi_kcs_ops_premem.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/io.h>
4 #include <console/console.h>
5 #include <device/pnp.h>
6 #include <delay.h>
7 #include <timer.h>
8 
9 #include "ipmi_kcs.h"
10 #include "chip.h"
11 
12 static int ipmi_get_bmc_self_test_result(const struct device *dev,
13  struct ipmi_selftest_rsp *rsp)
14 {
15  int ret;
16 
19  sizeof(*rsp));
20 
21  if (ret < sizeof(struct ipmi_rsp) || rsp->resp.completion_code) {
22  printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n",
23  __func__, ret, rsp->resp.completion_code);
24  return 1;
25  }
26  if (ret != sizeof(*rsp)) {
27  printk(BIOS_ERR, "IPMI: %s response truncated\n", __func__);
28  return 1;
29  }
30 
31  return 0;
32 }
33 
34 enum cb_err ipmi_kcs_premem_init(const u16 port, const u16 device)
35 {
36  const struct drivers_ipmi_config *conf = NULL;
37  struct ipmi_selftest_rsp selftestrsp = {0};
38  uint8_t retry_count;
39  const struct device *dev;
40 
41  /* Find IPMI PNP device from devicetree in romstage */
43 
44  if (!dev) {
45  printk(BIOS_ERR, "IPMI: Cannot find PNP device port: %x, device %x\n",
46  port, device);
47  return CB_ERR;
48  }
49  if (!dev->enabled) {
50  printk(BIOS_ERR, "IPMI: device is not enabled\n");
51  return CB_ERR;
52  }
53  printk(BIOS_DEBUG, "IPMI: romstage PNP KCS 0x%x\n", dev->path.pnp.port);
54  if (dev->chip_info)
55  conf = dev->chip_info;
56 
57  if (conf && conf->wait_for_bmc && conf->bmc_boot_timeout) {
58  struct stopwatch sw;
60  printk(BIOS_DEBUG, "IPMI: Waiting for BMC...\n");
61 
62  while (!stopwatch_expired(&sw)) {
63  if (inb(dev->path.pnp.port) != 0xff)
64  break;
65  mdelay(100);
66  }
67  if (stopwatch_expired(&sw)) {
68  printk(BIOS_INFO, "IPMI: Waiting for BMC timed out\n");
69  return CB_ERR;
70  }
71  }
72 
73  printk(BIOS_INFO, "Get BMC self test result...");
74  if (conf && conf->bmc_boot_timeout) {
75  for (retry_count = 0; retry_count < conf->bmc_boot_timeout; retry_count++) {
76  if (!ipmi_get_bmc_self_test_result(dev, &selftestrsp))
77  break;
78 
79  mdelay(1000);
80  }
81  } else {
82  /* At least run once */
83  ipmi_get_bmc_self_test_result(dev, &selftestrsp);
84  }
85 
86  int ret = CB_ERR;
87  switch (selftestrsp.result) {
88  case IPMI_APP_SELFTEST_NO_ERROR: /* 0x55 */
89  printk(BIOS_DEBUG, "No Error\n");
90  ret = CB_SUCCESS;
91  break;
92  case IPMI_APP_SELFTEST_NOT_IMPLEMENTED: /* 0x56 */
93  printk(BIOS_DEBUG, "Function Not Implemented\n");
94  ret = CB_SUCCESS;
95  break;
96  case IPMI_APP_SELFTEST_ERROR: /* 0x57 */
97  printk(BIOS_ERR, "Corrupted or inaccessible data or device\n");
98  break;
99  case IPMI_APP_SELFTEST_FATAL_HW_ERROR: /* 0x58 */
100  printk(BIOS_ERR, "Fatal Hardware Error\n");
101  break;
102  case IPMI_APP_SELFTEST_RESERVED: /* 0xFF */
103  printk(BIOS_DEBUG, "Reserved\n");
104  ret = CB_SUCCESS;
105  break;
106 
107  default: /* Other Device Specific Hardware Error */
108  printk(BIOS_ERR, "Device Specific Error 0x%x 0x%x\n", selftestrsp.result,
109  selftestrsp.param);
110  break;
111  }
112  return ret;
113 }
cb_err
coreboot error codes
Definition: cb_err.h:15
@ CB_ERR
Generic error code.
Definition: cb_err.h:17
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
#define printk(level,...)
Definition: stdlib.h:16
void mdelay(unsigned int msecs)
Definition: delay.c:2
u8 inb(u16 port)
DEVTREE_CONST struct device * dev_find_slot_pnp(u16 port, u16 device)
Given a PnP port and a device number, find the device structure.
Definition: device_const.c:331
port
Definition: i915.h:29
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
int ipmi_kcs_message(int port, int netfn, int lun, int cmd, const unsigned char *inmsg, int inlen, unsigned char *outmsg, int outlen)
Definition: ipmi_kcs.c:222
#define IPMI_APP_SELFTEST_NOT_IMPLEMENTED
Definition: ipmi_kcs.h:16
#define IPMI_APP_SELFTEST_RESERVED
Definition: ipmi_kcs.h:14
#define IPMI_NETFN_APPLICATION
Definition: ipmi_kcs.h:9
#define IPMI_BMC_GET_SELFTEST_RESULTS
Definition: ipmi_kcs.h:13
#define IPMI_APP_SELFTEST_ERROR
Definition: ipmi_kcs.h:17
#define IPMI_APP_SELFTEST_FATAL_HW_ERROR
Definition: ipmi_kcs.h:18
#define IPMI_APP_SELFTEST_NO_ERROR
Definition: ipmi_kcs.h:15
static int ipmi_get_bmc_self_test_result(const struct device *dev, struct ipmi_selftest_rsp *rsp)
enum cb_err ipmi_kcs_premem_init(const u16 port, const u16 device)
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define NULL
Definition: stddef.h:19
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
unsigned char uint8_t
Definition: stdint.h:8
struct pnp_path pnp
Definition: path.h:117
Definition: device.h:107
struct device_path path
Definition: device.h:115
DEVTREE_CONST void * chip_info
Definition: device.h:164
unsigned int enabled
Definition: device.h:122
bool wait_for_bmc
Definition: chip.h:33
u16 bmc_boot_timeout
Definition: chip.h:38
uint8_t completion_code
Definition: ipmi_kcs.h:41
struct ipmi_rsp resp
Definition: ipmi_kcs.h:59
uint8_t param
Definition: ipmi_kcs.h:61
uint8_t result
Definition: ipmi_kcs.h:60
unsigned int port
Definition: path.h:58