1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) Siemens AG, 2025
*/
#include <dm.h>
#include <sysinfo.h>
#include <net.h>
#include <u-boot/uuid.h>
#include <asm/arch/hardware.h>
#include "iot2050.h"
#define IOT2050_INFO_MAGIC 0x20502050
#define IOT2050_UUID_STR_LEN (32)
struct iot2050_info {
u32 magic;
u16 size;
char name[20 + 1];
char serial[16 + 1];
char mlfb[18 + 1];
char uuid[IOT2050_UUID_STR_LEN + 1];
char a5e[18 + 1];
u8 mac_addr_cnt;
u8 mac_addr[8][ARP_HLEN];
char seboot_version[40 + 1];
u8 padding[3];
u32 ddr_size_mb;
} __packed;
/**
* struct sysinfo_iot2050_priv - sysinfo private data
* @info: iot2050 board info
*/
struct sysinfo_iot2050_priv {
struct iot2050_info *info;
u8 uuid_smbios[16];
};
static int sysinfo_iot2050_detect(struct udevice *dev)
{
struct sysinfo_iot2050_priv *priv = dev_get_priv(dev);
if (!priv->info || priv->info->magic != IOT2050_INFO_MAGIC)
return -EFAULT;
return 0;
}
static int sysinfo_iot2050_get_str(struct udevice *dev, int id, size_t size,
char *val)
{
struct sysinfo_iot2050_priv *priv = dev_get_priv(dev);
switch (id) {
case BOARD_NAME:
case SYSID_SM_BASEBOARD_VERSION:
strlcpy(val, priv->info->name, size);
break;
case SYSID_SM_SYSTEM_SERIAL:
strlcpy(val, priv->info->serial, size);
break;
case BOARD_MLFB:
case SYSID_SM_SYSTEM_VERSION:
strlcpy(val, priv->info->mlfb, size);
break;
case BOARD_UUID:
strlcpy(val, priv->info->uuid, size);
break;
case BOARD_A5E:
case SYSID_SM_BASEBOARD_PRODUCT:
strlcpy(val, priv->info->a5e, size);
break;
case BOARD_SEBOOT_VER:
case SYSID_PRIOR_STAGE_VERSION:
strlcpy(val, priv->info->seboot_version, size);
break;
default:
return -EINVAL;
};
val[size - 1] = '\0';
return 0;
}
static int sysinfo_iot2050_get_int(struct udevice *dev, int id, int *val)
{
struct sysinfo_iot2050_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSID_BOARD_RAM_SIZE_MB:
*val = priv->info->ddr_size_mb;
return 0;
default:
return -EINVAL;
};
}
static int sysinfo_iot2050_get_data(struct udevice *dev, int id, void **data,
size_t *size)
{
struct sysinfo_iot2050_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSID_SM_SYSTEM_UUID:
*data = priv->uuid_smbios;
*size = 16;
return 0;
default:
return -EINVAL;
};
}
static int sysinfo_iot2050_get_item_count(struct udevice *dev, int id)
{
struct sysinfo_iot2050_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSID_BOARD_MAC_ADDR:
return priv->info->mac_addr_cnt;
default:
return -EINVAL;
};
}
static int sysinfo_iot2050_get_data_by_index(struct udevice *dev, int id,
int index, void **data,
size_t *size)
{
struct sysinfo_iot2050_priv *priv = dev_get_priv(dev);
switch (id) {
case SYSID_BOARD_MAC_ADDR:
if (index >= priv->info->mac_addr_cnt)
return -EINVAL;
*data = priv->info->mac_addr[index];
*size = ARP_HLEN;
return 0;
default:
return -EINVAL;
};
}
static const struct sysinfo_ops sysinfo_iot2050_ops = {
.detect = sysinfo_iot2050_detect,
.get_str = sysinfo_iot2050_get_str,
.get_int = sysinfo_iot2050_get_int,
.get_data = sysinfo_iot2050_get_data,
.get_item_count = sysinfo_iot2050_get_item_count,
.get_data_by_index = sysinfo_iot2050_get_data_by_index,
};
/**
* @brief Convert the IOT2050 UUID string to the SMBIOS format
*
* @param uuid_raw The IOT2050 UUID string parsed from the eeprom
* @param uuid_smbios The buffer to hold the SMBIOS formatted UUID
*/
static void sysinfo_iot2050_convert_uuid(const char *uuid_iot2050,
u8 *uuid_smbios)
{
char uuid_rfc4122_str[IOT2050_UUID_STR_LEN + 4 + 1] = {0};
char *tmp = uuid_rfc4122_str;
for (int i = 0; i < 16; i++) {
memcpy(tmp, uuid_iot2050 + i * 2, 2);
tmp += 2;
if (i == 3 || i == 5 || i == 7 || i == 9)
*tmp++ = '-';
}
uuid_str_to_bin(uuid_rfc4122_str, uuid_smbios, UUID_STR_FORMAT_GUID);
}
static int sysinfo_iot2050_probe(struct udevice *dev)
{
struct sysinfo_iot2050_priv *priv = dev_get_priv(dev);
unsigned long offset;
offset = dev_read_u32_default(dev, "offset",
TI_SRAM_SCRATCH_BOARD_EEPROM_START);
priv->info = (struct iot2050_info *)offset;
sysinfo_iot2050_convert_uuid(priv->info->uuid, priv->uuid_smbios);
return 0;
}
static const struct udevice_id sysinfo_iot2050_ids[] = {
{ .compatible = "siemens,sysinfo-iot2050" },
{ /* sentinel */ }
};
U_BOOT_DRIVER(sysinfo_iot2050) = {
.name = "sysinfo_iot2050",
.id = UCLASS_SYSINFO,
.of_match = sysinfo_iot2050_ids,
.ops = &sysinfo_iot2050_ops,
.priv_auto = sizeof(struct sysinfo_iot2050_priv),
.probe = sysinfo_iot2050_probe,
};
|