2 * This file is part of the coreboot project.
4 * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <console/console.h>
18 #include <cpu/x86/smm.h>
21 #define GSMI_RET_SUCCESS 0x00
22 #define GSMI_RET_INVALID_PARAMETER 0x82
23 #define GSMI_RET_UNSUPPORTED 0x83
25 #define GSMI_CMD_SET_EVENT_LOG 0x08
26 #define GSMI_CMD_CLEAR_EVENT_LOG 0x09
27 #define GSMI_CMD_HANDSHAKE_TYPE 0xc1
29 #define GSMI_HANDSHAKE_NONE 0x7f
30 #define GSMI_LOG_ENTRY_TYPE_KERNEL 0xDEAD
32 struct gsmi_set_eventlog_param
{
36 } __attribute__ ((packed
));
38 struct gsmi_set_eventlog_type1
{
41 } __attribute__ ((packed
));
43 struct gsmi_clear_eventlog_param
{
46 } __attribute__ ((packed
));
48 /* Param is usually EBX, ret in EAX */
49 u32
gsmi_exec(u8 command
, u32
*param
)
51 struct gsmi_set_eventlog_param
*sel
;
52 struct gsmi_set_eventlog_type1
*type1
;
53 struct gsmi_clear_eventlog_param
*cel
;
54 u32 ret
= GSMI_RET_UNSUPPORTED
;
57 case GSMI_CMD_HANDSHAKE_TYPE
:
58 /* Used by kernel to verify basic SMI functionality */
59 printk(BIOS_DEBUG
, "GSMI Handshake\n");
60 ret
= GSMI_HANDSHAKE_NONE
;
63 case GSMI_CMD_SET_EVENT_LOG
:
64 /* Look for a type1 event */
65 sel
= (struct gsmi_set_eventlog_param
*)(*param
);
69 /* Make sure the input is usable */
70 if (sel
->type
!= 1 && sel
->data_ptr
!= 0 &&
71 sel
->data_len
!= sizeof(struct gsmi_set_eventlog_type1
))
74 /* Event structure within the data buffer */
75 type1
= (struct gsmi_set_eventlog_type1
*)(sel
->data_ptr
);
79 printk(BIOS_DEBUG
, "GSMI Set Event Log "
80 "(type=0x%x instance=0x%x)\n",
81 type1
->type
, type1
->instance
);
83 if (type1
->type
== GSMI_LOG_ENTRY_TYPE_KERNEL
) {
84 /* Special case for linux kernel shutdown reason */
85 elog_add_event_dword(ELOG_TYPE_OS_EVENT
,
88 /* Add other events that may be used for testing */
89 elog_add_event_dword(type1
->type
, type1
->instance
);
91 ret
= GSMI_RET_SUCCESS
;
94 case GSMI_CMD_CLEAR_EVENT_LOG
:
95 /* Get parameter buffer even though we don't use it */
96 cel
= (struct gsmi_clear_eventlog_param
*)(*param
);
100 printk(BIOS_DEBUG
, "GSMI Clear Event Log (%u%% type=%u)\n",
101 cel
->percentage
, cel
->data_type
);
103 if (elog_clear() == 0)
104 ret
= GSMI_RET_SUCCESS
;
108 printk(BIOS_DEBUG
, "GSMI Unknown: 0x%02x\n", command
);