blob: ba249a94d7a1f71cfa93a5421dceb2415d769520 [file] [log] [blame]
Angel Pons56c1c4d2023-03-22 13:25:09 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
4#include <string.h>
5#include <types.h>
6
7#include "ec.h"
8#include "mainboard.h"
9#include "vpd.h"
10
Angel Ponsb3274252023-05-10 21:57:45 +020011static void write_invalid_str(char *dest, size_t length)
12{
13 snprintf(dest, length, "%s", "INVALID");
14}
15
Angel Ponsd4c5fc02023-03-27 12:06:08 +020016const struct emi_eeprom_vpd *get_emi_eeprom_vpd(void)
Angel Pons56c1c4d2023-03-22 13:25:09 +010017{
Angel Ponsd4c5fc02023-03-27 12:06:08 +020018 static union {
19 struct emi_eeprom_vpd layout;
20 uint8_t raw[sizeof(struct emi_eeprom_vpd)];
21 } vpd = {0};
Angel Pons56c1c4d2023-03-22 13:25:09 +010022
23 /* Check if cached VPD is valid */
Angel Ponsd4c5fc02023-03-27 12:06:08 +020024 if (vpd.layout.header.revision == VPD_LATEST_REVISION)
25 return &vpd.layout;
Angel Pons56c1c4d2023-03-22 13:25:09 +010026
27 ec_emi_read(vpd.raw, EMI_0_IO_BASE_ADDR, 0, 0, sizeof(vpd.raw));
28
29 /* If the magic value doesn't match, consider EEPROM VPD unreliable */
Angel Ponsd4c5fc02023-03-27 12:06:08 +020030 if (vpd.layout.header.magic != VPD_MAGIC) {
Angel Pons56c1c4d2023-03-22 13:25:09 +010031 printk(BIOS_WARNING, "Atlas VPD: Bad magic value, using fallback defaults\n");
Angel Ponsd4c5fc02023-03-27 12:06:08 +020032 vpd.layout.header.revision = 0;
Angel Pons56c1c4d2023-03-22 13:25:09 +010033 } else {
Angel Ponsd4c5fc02023-03-27 12:06:08 +020034 printk(BIOS_DEBUG, "Atlas VPD: Got revision %u from EC\n",
35 vpd.layout.header.revision);
Angel Pons56c1c4d2023-03-22 13:25:09 +010036 }
37
38 /*
39 * For backwards compatibility, if the VPD from the EC is an older
40 * version, uprev it to the latest version coreboot knows about by
41 * filling in the remaining fields with default values. Should the
42 * EC provide a newer VPD revision, coreboot would downgrade it to
43 * the latest version it knows about as the VPD layout is designed
44 * to be backwards compatible.
45 *
46 * Whenever the value of `VPD_LATEST_REVISION` is incremented, add
47 * a new `case` label just before the `default` label that matches
48 * the second latest revision to initialise the newly-added fields
49 * of the VPD structure with a reasonable fallback value. Note the
50 * intentional falling through.
51 */
Angel Ponsd4c5fc02023-03-27 12:06:08 +020052 switch (vpd.layout.header.revision) {
Angel Pons56c1c4d2023-03-22 13:25:09 +010053 case 0:
54 memset(vpd.raw, 0, sizeof(vpd.raw));
Angel Ponsd4c5fc02023-03-27 12:06:08 +020055 vpd.layout.header.magic = VPD_MAGIC;
Angel Ponsb3274252023-05-10 21:57:45 +020056 write_invalid_str(vpd.layout.serial_number, sizeof(vpd.layout.serial_number));
57 write_invalid_str(vpd.layout.part_number, sizeof(vpd.layout.part_number));
Angel Ponsd4c5fc02023-03-27 12:06:08 +020058 vpd.layout.profile = ATLAS_PROF_UNPROGRAMMED;
Angel Pons56c1c4d2023-03-22 13:25:09 +010059 __fallthrough;
60 default:
61 /* Ensure serial numbers are NULL-terminated, update revision last */
Angel Ponsd4c5fc02023-03-27 12:06:08 +020062 vpd.layout.serial_number[ATLAS_SN_PN_LENGTH - 1] = '\0';
63 vpd.layout.part_number[ATLAS_SN_PN_LENGTH - 1] = '\0';
64 vpd.layout.header.revision = VPD_LATEST_REVISION;
Angel Pons56c1c4d2023-03-22 13:25:09 +010065 break;
66 }
67
Angel Ponsd4c5fc02023-03-27 12:06:08 +020068 return &vpd.layout;
Angel Pons56c1c4d2023-03-22 13:25:09 +010069}