coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
early_me_mrc.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 <device/pci_def.h>
8 #include <halt.h>
10 
11 #include "me.h"
12 #include "pch.h"
13 
14 static const char *me_ack_values[] = {
15  [ME_HFS_ACK_NO_DID] = "No DID Ack received",
16  [ME_HFS_ACK_RESET] = "Non-power cycle reset",
17  [ME_HFS_ACK_PWR_CYCLE] = "Power cycle reset",
18  [ME_HFS_ACK_S3] = "Go to S3",
19  [ME_HFS_ACK_S4] = "Go to S4",
20  [ME_HFS_ACK_S5] = "Go to S5",
21  [ME_HFS_ACK_GBL_RESET] = "Global Reset",
22  [ME_HFS_ACK_CONTINUE] = "Continue to boot"
23 };
24 
26 {
27  union me_hfs hfs;
28  union me_gmes gmes;
30 
31  if ((id == 0xffffffff) || (id == 0x00000000) ||
32  (id == 0x0000ffff) || (id == 0xffff0000)) {
33  printk(BIOS_DEBUG, "Missing Intel ME PCI device.\n");
34  } else {
37 
38  intel_me_status(&hfs, &gmes);
39  }
40 }
41 
43 {
44  int count;
45  union me_uma uma;
46  union me_hfs hfs;
47 
48  printk(BIOS_INFO, "Intel ME early init\n");
49 
50  /* Wait for ME UMA SIZE VALID bit to be set */
51  for (count = ME_RETRY; count > 0; --count) {
53  if (uma.valid)
54  break;
56  }
57  if (!count) {
58  printk(BIOS_ERR, "ME is not ready!\n");
59  return -1;
60  }
61 
62  /* Check for valid firmware */
64  if (hfs.fpt_bad) {
65  printk(BIOS_WARNING, "ME has bad firmware\n");
66  return -1;
67  }
68 
69  printk(BIOS_INFO, "Intel ME firmware is ready\n");
70  return 0;
71 }
72 
74 {
75  union me_uma uma;
76 
78  if (uma.valid) {
79  printk(BIOS_DEBUG, "ME: Requested %uMB UMA\n", uma.size);
80  return uma.size;
81  }
82 
83  printk(BIOS_DEBUG, "ME: Invalid UMA size\n");
84  return 0;
85 }
86 
88 {
89  u8 reset;
90  int count;
91  u32 mebase_l, mebase_h;
92  union me_hfs hfs;
93  union me_did did = {
94  .init_done = ME_INIT_DONE,
95  .status = status
96  };
97 
98  /* MEBASE from MESEG_BASE[35:20] */
101  did.uma_base = (mebase_l >> 20) | (mebase_h << 12);
102 
103  /* Send message to ME */
104  printk(BIOS_DEBUG, "ME: Sending Init Done with status: %d, "
105  "UMA base: 0x%04x\n", status, did.uma_base);
106 
108 
109  /* Must wait for ME acknowledgement */
110  for (count = ME_RETRY; count > 0; --count) {
112  if (hfs.bios_msg_ack)
113  break;
114  udelay(ME_DELAY);
115  }
116  if (!count) {
117  printk(BIOS_ERR, "ME failed to respond\n");
118  return -1;
119  }
120 
121  /* Return the requested BIOS action */
122  printk(BIOS_NOTICE, "ME: Requested BIOS Action: %s\n",
123  me_ack_values[hfs.ack_data]);
124 
125  /* Check status after acknowledgement */
127 
128  reset = 0;
129  switch (hfs.ack_data) {
130  case ME_HFS_ACK_CONTINUE:
131  /* Continue to boot */
132  return 0;
133  case ME_HFS_ACK_RESET:
134  /* Non-power cycle reset */
135  set_global_reset(0);
136  reset = 0x06;
137  break;
139  /* Power cycle reset */
140  set_global_reset(0);
141  reset = 0x0e;
142  break;
144  /* Global reset */
145  set_global_reset(1);
146  reset = 0x0e;
147  break;
148  case ME_HFS_ACK_S3:
149  case ME_HFS_ACK_S4:
150  case ME_HFS_ACK_S5:
151  break;
152  }
153 
154  /* Perform the requested reset */
155  if (reset) {
156  outb(reset, 0xcf9);
157  halt();
158  }
159  return -1;
160 }
#define printk(level,...)
Definition: stdlib.h:16
uint16_t did
Definition: tis.c:16
void outb(u8 val, u16 port)
int intel_early_me_init(void)
Definition: early_me_mrc.c:42
void intel_early_me_status(void)
Definition: early_me_mrc.c:25
static const char * me_ack_values[]
Definition: early_me_mrc.c:14
int intel_early_me_uma_size(void)
Definition: early_me_mrc.c:73
int intel_early_me_init_done(u8 status)
Definition: early_me_mrc.c:87
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
#define PCI_VENDOR_ID
Definition: pci_def.h:8
#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 PCI_CPU_MEBASE_H
Definition: me.h:16
#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 PCI_CPU_DEVICE
Definition: me.h:16
#define PCI_ME_GMES
Definition: me.h:101
#define PCH_ME_DEV
Definition: pch.h:79
void set_global_reset(const bool enable)
Definition: me.c:17
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: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
Definition: me.h:110
u32 raw
Definition: me.h:127
#define count