coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
smbios.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <console/console.h>
4 #include <device/device.h>
6 #include <delay.h>
7 #include <cpu/x86/mp.h>
8 #include <timer.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <soc/soc_util.h>
12 #include <soc/util.h>
13 #include <smbios.h>
14 #include <types.h>
15 
16 #include "ocp_dmi.h"
17 
18 #define PPIN_STR_LEN 17
19 
20 struct fru_info_str fru_strings = {0};
21 /* The spec defines only at most 2 sockets */
23 static bool remote_ppin_done = false;
24 
25 /* Override SMBIOS type 1 data. */
26 const char *smbios_system_manufacturer(void)
27 {
29  return (const char *)fru_strings.prod_info.manufacturer;
30  else
31  return CONFIG_MAINBOARD_SMBIOS_MANUFACTURER;
32 }
33 
34 const char *smbios_system_product_name(void)
35 {
37  return (const char *)fru_strings.prod_info.product_name;
38  else
39  return CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME;
40 }
41 
42 const char *smbios_system_serial_number(void)
43 {
45  return (const char *)fru_strings.prod_info.serial_number;
46  else
47  return CONFIG_MAINBOARD_SERIAL_NUMBER;
48 }
49 
50 const char *smbios_system_version(void)
51 {
53  return (const char *)fru_strings.prod_info.product_version;
54  else
55  return CONFIG_MAINBOARD_VERSION;
56 }
57 
58 /* Override SMBIOS type 1 uuid from the value from BMC. */
60 {
61  ipmi_get_system_guid(CONFIG_BMC_KCS_BASE, uuid);
62 }
63 
64 /* Override SMBIOS type 2 data. */
65 const char *smbios_mainboard_version(void)
66 {
68  return (const char *)fru_strings.board_info.part_number;
69  else
70  return CONFIG_MAINBOARD_VERSION;
71 }
72 
74 {
76  return (const char *)fru_strings.board_info.manufacturer;
77  else
78  return CONFIG_MAINBOARD_SMBIOS_MANUFACTURER;
79 }
80 
82 {
84  return (const char *)fru_strings.board_info.product_name;
85  else
86  return CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME;
87 }
88 
90 {
92  return (const char *)fru_strings.board_info.serial_number;
93  else
94  return CONFIG_MAINBOARD_SERIAL_NUMBER;
95 }
96 
97 /* Override SMBIOS type 2 and 3 asset_tag data. */
98 const char *smbios_mainboard_asset_tag(void)
99 {
101  return (const char *)fru_strings.prod_info.asset_tag;
102  else
103  return "";
104 }
105 
106 /* Override SMBIOS type 3 data. */
108 {
109  /* SMBIOS System Enclosure or Chassis Types are values from 0 to 20h. */
112  else
114 }
115 
116 const char *smbios_chassis_version(void)
117 {
120  else
121  return "";
122 }
123 
125 {
128  else
129  return "";
130 }
131 
132 /* Override SMBIOS type 4 processor serial numbers from FRU Chassis custom data. */
134 {
135  /* For now type 4 only creates for one CPU, so it can only write the serial number
136  * of CPU0.
137  */
140  else
141  return "";
142 }
143 
144 static void read_remote_ppin(void *data)
145 {
146  *(msr_t *)data = read_msr_ppin();
147  remote_ppin_done = true;
148 }
149 
150 static void wait_for_remote_ppin(void)
151 {
152  struct stopwatch sw;
153 
154  stopwatch_init_msecs_expire(&sw, 500);
155  while (!stopwatch_expired(&sw)) {
156  if (remote_ppin_done)
157  break;
158  mdelay(100);
159  }
160  if (stopwatch_expired(&sw))
161  printk(BIOS_ERR, "Wait for read_remote_ppin() timeout\n");
162 }
163 
164 int smbios_add_oem_string(u8 *start, const char *str)
165 {
166  int i = 1;
167  char *p = (char *)start;
168 
169  if (*str == '\0')
170  return 0;
171 
172  for (;;) {
173  if (!*p) {
174  strcpy(p, str);
175  p += strlen(str);
176  *p++ = '\0';
177  *p++ = '\0';
178  return i;
179  }
180 
181  p += strlen(p)+1;
182  i++;
183  }
184 }
185 
186 /* When the most significant 4 bits of PPIN hi/lo are 0, add '0' to the beginning */
187 static void ppin_string_fixup(int i, char *ppin)
188 {
189  if ((xeon_sp_ppin[i].hi & 0xf0000000) == 0) {
190  if ((xeon_sp_ppin[i].lo & 0xf0000000) == 0)
191  snprintf(ppin, PPIN_STR_LEN, "0%x0%x", xeon_sp_ppin[i].hi,
192  xeon_sp_ppin[i].lo);
193  else
194  snprintf(ppin, PPIN_STR_LEN, "0%x%x", xeon_sp_ppin[i].hi,
195  xeon_sp_ppin[i].lo);
196  } else if ((xeon_sp_ppin[i].lo & 0xf0000000) == 0) {
197  snprintf(ppin, PPIN_STR_LEN, "%x0%x", xeon_sp_ppin[i].hi, xeon_sp_ppin[i].lo);
198  } else {
199  snprintf(ppin, PPIN_STR_LEN, "%x%x", xeon_sp_ppin[i].hi, xeon_sp_ppin[i].lo);
200  }
201 }
202 
203 /*
204  * Override SMBIOS type 11 OEM string 1 to string 6, the rest are project dependent
205  * and can be added in the mainboard code.
206  */
207 void ocp_oem_smbios_strings(struct device *dev, struct smbios_type11 *t)
208 {
209  char ppin[PPIN_STR_LEN];
210 
211  /* Add OEM string 1 to 4 */
215  else
217 
221  else
223 
228  else
230 
235  } else {
237  }
238 
239  /* Add CPU0 PPIN to OEM string 5 */
241  ppin_string_fixup(0, ppin);
242  t->count = smbios_add_oem_string(t->eos, ppin);
243 
244  /* Add CPU1 PPIN to OEM string 6 */
245  if (CONFIG_MAX_SOCKET == 2 && CONFIG(PARALLEL_MP_AP_WORK)) {
246  /* Read the last CPU MSR */
249  CB_SUCCESS) {
250  printk(BIOS_ERR, "Failed to read remote PPIN.\n");
252  } else {
253  /* Wait for read_remote_ppin() to finish because it's executed
254  in parallel */
256  ppin_string_fixup(1, ppin);
257  t->count = smbios_add_oem_string(t->eos, ppin);
258  }
259  } else {
260  t->count = smbios_add_oem_string(t->eos, "0000");
261  }
262 }
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
#define printk(level,...)
Definition: stdlib.h:16
enum cb_err mp_run_on_aps(void(*func)(void *), void *arg, int logical_cpu_num, long expire_us)
Definition: mp_init.c:971
void mdelay(unsigned int msecs)
Definition: delay.c:2
const char * smbios_chassis_version(void)
Definition: smbios.c:116
#define PPIN_STR_LEN
Definition: smbios.c:18
const char * smbios_system_version(void)
Definition: smbios.c:50
void smbios_system_set_uuid(u8 *uuid)
Definition: smbios.c:59
smbios_enclosure_type smbios_mainboard_enclosure_type(void)
Definition: smbios.c:107
static bool remote_ppin_done
Definition: smbios.c:23
void ocp_oem_smbios_strings(struct device *dev, struct smbios_type11 *t)
Definition: smbios.c:207
const char * smbios_mainboard_serial_number(void)
Definition: smbios.c:89
const char * smbios_chassis_serial_number(void)
Definition: smbios.c:124
const char * smbios_system_product_name(void)
Definition: smbios.c:34
const char * smbios_mainboard_version(void)
Definition: smbios.c:65
const char * smbios_mainboard_manufacturer(void)
Definition: smbios.c:73
const char * smbios_processor_serial_number(void)
Definition: smbios.c:133
const char * smbios_mainboard_product_name(void)
Definition: smbios.c:81
const char * smbios_system_serial_number(void)
Definition: smbios.c:42
msr_t xeon_sp_ppin[2]
Definition: smbios.c:22
const char * smbios_mainboard_asset_tag(void)
Definition: smbios.c:98
const char * smbios_system_manufacturer(void)
Definition: smbios.c:26
struct fru_info_str fru_strings
Definition: smbios.c:20
static void ppin_string_fixup(int i, char *ppin)
Definition: smbios.c:187
static void read_remote_ppin(void *data)
Definition: smbios.c:144
static void wait_for_remote_ppin(void)
Definition: smbios.c:150
int smbios_add_oem_string(u8 *start, const char *str)
Definition: smbios.c:164
@ CONFIG
Definition: dsi_common.h:201
smbios_enclosure_type
Definition: smbios.h:374
@ SMBIOS_ENCLOSURE_RACK_MOUNT_CHASSIS
Definition: smbios.h:397
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
#define USECS_PER_MSEC
Definition: timer.h:10
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
enum cb_err ipmi_get_system_guid(const int port, uint8_t *uuid)
Definition: ipmi_ops.c:96
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define TBF
Definition: ocp_dmi.h:10
int get_platform_thread_count(void)
Definition: util.c:84
msr_t read_msr_ppin(void)
Definition: util.c:46
#define NULL
Definition: stddef.h:19
uint8_t u8
Definition: stdint.h:45
char * strcpy(char *dst, const char *src)
Definition: string.c:92
size_t strlen(const char *src)
Definition: string.c:42
Definition: device.h:107
char * product_name
Definition: ipmi_ops.h:119
size_t custom_count
Definition: ipmi_ops.h:124
char * serial_number
Definition: ipmi_ops.h:120
char ** board_custom
Definition: ipmi_ops.h:123
char * part_number
Definition: ipmi_ops.h:121
char * manufacturer
Definition: ipmi_ops.h:118
uint8_t chassis_type
Definition: ipmi_ops.h:128
char * chassis_partnumber
Definition: ipmi_ops.h:129
char ** chassis_custom
Definition: ipmi_ops.h:131
char * serial_number
Definition: ipmi_ops.h:130
struct fru_board_info board_info
Definition: ipmi_ops.h:137
struct fru_product_info prod_info
Definition: ipmi_ops.h:136
struct fru_chassis_info chassis_info
Definition: ipmi_ops.h:138
char * manufacturer
Definition: ipmi_ops.h:106
char * asset_tag
Definition: ipmi_ops.h:111
size_t custom_count
Definition: ipmi_ops.h:114
char * product_name
Definition: ipmi_ops.h:107
char * serial_number
Definition: ipmi_ops.h:110
char * product_version
Definition: ipmi_ops.h:109
char ** product_custom
Definition: ipmi_ops.h:113
u8 eos[2]
Definition: smbios.h:815
struct mono_time start
Definition: timer.h:112
int snprintf(char *buf, size_t size, const char *fmt,...)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: vsprintf.c:35