coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
gsmi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <elog.h>
5 
6 #define GSMI_RET_SUCCESS 0x00
7 #define GSMI_RET_INVALID_PARAMETER 0x82
8 #define GSMI_RET_UNSUPPORTED 0x83
9 
10 #define GSMI_CMD_SET_EVENT_LOG 0x08
11 #define GSMI_CMD_CLEAR_EVENT_LOG 0x09
12 #define GSMI_CMD_LOG_S0IX_SUSPEND 0x0a
13 #define GSMI_CMD_LOG_S0IX_RESUME 0x0b
14 #define GSMI_CMD_HANDSHAKE_TYPE 0xc1
15 
16 #define GSMI_HANDSHAKE_NONE 0x7f
17 #define GSMI_LOG_ENTRY_TYPE_KERNEL 0xDEAD
18 
24 
28 } __packed;
29 
33 } __packed;
34 
36 {
37  /* Default weak implementation, does nothing. */
38 }
39 
41 {
42  /* Default weak implementation, does nothing. */
43 }
44 
45 /* Param is usually EBX, ret in EAX */
46 u32 gsmi_exec(u8 command, u32 *param)
47 {
48  struct gsmi_set_eventlog_param *sel;
49  struct gsmi_set_eventlog_type1 *type1;
50  struct gsmi_clear_eventlog_param *cel;
52 
53  switch (command) {
55  /* Used by kernel to verify basic SMI functionality */
56  printk(BIOS_DEBUG, "GSMI Handshake\n");
57  ret = GSMI_HANDSHAKE_NONE;
58  break;
59 
61  /* Look for a type1 event */
62  sel = (struct gsmi_set_eventlog_param *)(*param);
63  if (!sel)
64  break;
65 
66  /* Make sure the input is usable */
67  if (sel->type != 1 && sel->data_ptr != 0 &&
68  sel->data_len != sizeof(struct gsmi_set_eventlog_type1))
69  break;
70 
71  /* Event structure within the data buffer */
72  type1 = (struct gsmi_set_eventlog_type1 *)(sel->data_ptr);
73  if (!type1)
74  break;
75 
76  printk(BIOS_DEBUG, "GSMI Set Event Log "
77  "(type=0x%x instance=0x%x)\n",
78  type1->type, type1->instance);
79 
80  if (type1->type == GSMI_LOG_ENTRY_TYPE_KERNEL) {
81  /* Special case for linux kernel shutdown reason */
83  type1->instance);
84  } else {
85  /* Add other events that may be used for testing */
86  elog_add_event_dword(type1->type, type1->instance);
87  }
88  ret = GSMI_RET_SUCCESS;
89  break;
90 
92  /* Get parameter buffer even though we don't use it */
93  cel = (struct gsmi_clear_eventlog_param *)(*param);
94  if (!cel)
95  break;
96 
97  printk(BIOS_DEBUG, "GSMI Clear Event Log (%u%% type=%u)\n",
98  cel->percentage, cel->data_type);
99 
100  if (elog_clear() == 0)
101  ret = GSMI_RET_SUCCESS;
102  break;
103 
106  ret = GSMI_RET_SUCCESS;
107 
108  if (command == GSMI_CMD_LOG_S0IX_SUSPEND)
110  else {
114  }
115  break;
116 
117  default:
118  printk(BIOS_DEBUG, "GSMI Unknown: 0x%02x\n", command);
119  break;
120  }
121 
122  return ret;
123 }
#define ELOG_TYPE_OS_EVENT
Definition: elog.h:74
#define ELOG_TYPE_S0IX_ENTER
Definition: elog.h:292
#define ELOG_TYPE_S0IX_EXIT
Definition: elog.h:293
#define printk(level,...)
Definition: stdlib.h:16
int elog_add_event_dword(u8 event_type, u32 data)
Definition: elog.c:878
int elog_clear(void)
Definition: elog.c:603
int elog_add_event(u8 event_type)
Definition: elog.c:863
void __weak elog_gsmi_cb_mainboard_log_wake_source(void)
Definition: gsmi.c:40
#define GSMI_CMD_LOG_S0IX_SUSPEND
Definition: gsmi.c:12
#define GSMI_RET_SUCCESS
Definition: gsmi.c:6
struct gsmi_set_eventlog_param __packed
#define GSMI_CMD_SET_EVENT_LOG
Definition: gsmi.c:10
void __weak elog_gsmi_cb_platform_log_wake_source(void)
Definition: gsmi.c:35
#define GSMI_RET_UNSUPPORTED
Definition: gsmi.c:8
#define GSMI_HANDSHAKE_NONE
Definition: gsmi.c:16
#define GSMI_CMD_LOG_S0IX_RESUME
Definition: gsmi.c:13
#define GSMI_LOG_ENTRY_TYPE_KERNEL
Definition: gsmi.c:17
u32 gsmi_exec(u8 command, u32 *param)
Definition: gsmi.c:46
#define GSMI_CMD_CLEAR_EVENT_LOG
Definition: gsmi.c:11
#define GSMI_CMD_HANDSHAKE_TYPE
Definition: gsmi.c:14
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
const struct smm_save_state_ops *legacy_ops __weak
Definition: save_state.c:8
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45