Loading...
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, }; |