coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
early_me.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/io.h>
4 #include <device/pci_ops.h>
5 #include <console/console.h>
6 #include <delay.h>
7 #include <halt.h>
8 
9 #include "me.h"
10 #include "pch.h"
11 
12 static const char *me_ack_values[] = {
13  [ME_HFS_ACK_NO_DID] = "No DID Ack received",
14  [ME_HFS_ACK_RESET] = "Non-power cycle reset",
15  [ME_HFS_ACK_PWR_CYCLE] = "Power cycle reset",
16  [ME_HFS_ACK_S3] = "Go to S3",
17  [ME_HFS_ACK_S4] = "Go to S4",
18  [ME_HFS_ACK_S5] = "Go to S5",
19  [ME_HFS_ACK_GBL_RESET] = "Global Reset",
20  [ME_HFS_ACK_CONTINUE] = "Continue to boot"
21 };
22 
24 {
25  union me_hfs hfs = { .raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS) };
26  union me_hfs2 hfs2 = { .raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS2) };
27 
28  intel_me_status(hfs, hfs2);
29 }
30 
32 {
33  int count;
34  union me_uma uma;
35  union me_hfs hfs;
36 
37  printk(BIOS_INFO, "Intel ME early init\n");
38 
39  /* Wait for ME UMA SIZE VALID bit to be set */
40  /* FIXME: ME9 BGW indicates a 5 sec poll timeout. */
41  for (count = ME_RETRY; count > 0; --count) {
43  if (uma.valid)
44  break;
46  }
47  if (!count) {
48  printk(BIOS_ERR, "ME is not ready!\n");
49  return -1;
50  }
51 
52  /* Check for valid firmware */
54  if (hfs.fpt_bad) {
55  printk(BIOS_WARNING, "ME has bad firmware\n");
56  return -1;
57  }
58 
59  printk(BIOS_INFO, "Intel ME firmware is ready\n");
60  return 0;
61 }
62 
64 {
65  union me_uma uma = { .raw = pci_read_config32(PCH_ME_DEV, PCI_ME_UMA) };
66 
67  if (uma.valid) {
68  printk(BIOS_DEBUG, "ME: Requested %uMB UMA\n", uma.size);
69  return uma.size;
70  }
71 
72  printk(BIOS_DEBUG, "ME: Invalid UMA size\n");
73  return 0;
74 }
75 
76 static inline void set_global_reset(int enable)
77 {
79 
80  /* CF9GR indicates a Global Reset */
81  if (enable)
82  pmir |= PMIR_CF9GR;
83  else
84  pmir &= ~PMIR_CF9GR;
85 
87 }
88 
90 {
91  u8 reset;
92  int count;
93  u32 mebase_l, mebase_h;
94  union me_hfs hfs;
95  union me_did did = {
96  .init_done = ME_INIT_DONE,
97  .status = status
98  };
99 
100  /* MEBASE from MESEG_BASE[35:20] */
103  did.uma_base = (mebase_l >> 20) | (mebase_h << 12);
104 
105  /* Send message to ME */
106  printk(BIOS_DEBUG, "ME: Sending Init Done with status: %d, "
107  "UMA base: 0x%04x\n", status, did.uma_base);
108 
110 
111  /*
112  * The ME firmware does not respond with an ACK when NOMEM or ERROR
113  * are sent.
114  */
116  return 0;
117 
118  /* Must wait for ME acknowledgement */
119  for (count = ME_RETRY; count > 0; --count) {
121  if (hfs.bios_msg_ack)
122  break;
123  udelay(ME_DELAY);
124  }
125  if (!count) {
126  printk(BIOS_ERR, "ME failed to respond\n");
127  return -1;
128  }
129 
130  /* Return the requested BIOS action */
131  printk(BIOS_NOTICE, "ME: Requested BIOS Action: %s\n",
132  me_ack_values[hfs.ack_data]);
133 
134  /* Check status after acknowledgement */
136 
137  reset = 0;
138  switch (hfs.ack_data) {
139  case ME_HFS_ACK_CONTINUE:
140  /* Continue to boot */
141  return 0;
142  case ME_HFS_ACK_RESET:
143  /* Non-power cycle reset */
144  set_global_reset(0);
145  reset = 0x06;
146  break;
148  /* Power cycle reset */
149  set_global_reset(0);
150  reset = 0x0e;
151  break;
153  /* Global reset */
154  set_global_reset(1);
155  reset = 0x0e;
156  break;
157  case ME_HFS_ACK_S3:
158  case ME_HFS_ACK_S4:
159  case ME_HFS_ACK_S5:
160  break;
161  }
162 
163  /* Perform the requested reset */
164  if (reset) {
165  outb(reset, 0xcf9);
166  halt();
167  }
168  return -1;
169 }
int intel_early_me_init(void)
Definition: early_me.c:43
void intel_early_me_status(void)
Definition: early_me.c:26
int intel_early_me_uma_size(void)
Definition: early_me.c:74
int intel_early_me_init_done(u8 status)
Definition: early_me.c:88
#define printk(level,...)
Definition: stdlib.h:16
uint16_t did
Definition: tis.c:16
void outb(u8 val, u16 port)
void __noreturn halt(void)
halt the system reliably
Definition: halt.c:6
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_NOTICE
BIOS_NOTICE - Unexpected but relatively insignificant.
Definition: loglevel.h:100
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
static const char * me_ack_values[]
Definition: early_me.c:12
static void set_global_reset(int enable)
Definition: early_me.c:76
#define PMIR
Definition: lpc.h:72
#define PMIR_CF9GR
Definition: lpc.h:74
#define ME_HFS_ACK_S3
Definition: me.h:45
#define PCI_CPU_MEBASE_L
Definition: me.h:15
#define ME_RETRY
Definition: me.h:8
#define ME_DELAY
Definition: me.h:9
#define ME_HFS_ACK_PWR_CYCLE
Definition: me.h:44
#define ME_INIT_STATUS_ERROR
Definition: me.h:81
#define ME_INIT_STATUS_NOMEM
Definition: me.h:80
#define PCI_CPU_MEBASE_H
Definition: me.h:16
#define PCI_ME_HFS2
Definition: me.h:100
#define ME_HFS_ACK_S4
Definition: me.h:46
#define ME_HFS_ACK_S5
Definition: me.h:47
#define ME_HFS_ACK_GBL_RESET
Definition: me.h:48
void intel_me_status(void)
Definition: me_status.c:194
#define ME_INIT_DONE
Definition: me.h:78
#define PCI_ME_UMA
Definition: me.h:67
#define ME_HFS_ACK_NO_DID
Definition: me.h:42
#define PCI_ME_HFS
Definition: me.h:18
#define ME_HFS_ACK_CONTINUE
Definition: me.h:49
#define PCI_ME_H_GS
Definition: me.h:77
#define ME_HFS_ACK_RESET
Definition: me.h:43
#define PCH_LPC_DEV
Definition: lpc.h:7
#define PCI_CPU_DEVICE
Definition: me.h:16
#define PCH_ME_DEV
Definition: pch.h:79
uint32_t u32
Definition: stdint.h:51
uint8_t u8
Definition: stdint.h:45
Definition: me.h:88
u32 status
Definition: me.h:92
Definition: me.h:170
u32 raw
Definition: me.h:194
Definition: me.h:51
u32 raw
Definition: me.h:69
u32 ack_data
Definition: me.h:63
u32 fpt_bad
Definition: me.h:54
u32 bios_msg_ack
Definition: me.h:64
Definition: me.h:69
u32 size
Definition: me.h:70
u32 raw
Definition: me.h:82
u32 valid
Definition: me.h:72
static void __noreturn reset(void)
void udelay(uint32_t us)
Definition: udelay.c:15
#define count