blob: 12371f71e6b7c1a55a59d0ef06e6aa58b06fe7c4 [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
11const union emi_eeprom_vpd *get_emi_eeprom_vpd(void)
12{
13 static union emi_eeprom_vpd vpd = {0};
14
15 /* Check if cached VPD is valid */
16 if (vpd.header.revision == VPD_LATEST_REVISION)
17 return &vpd;
18
19 ec_emi_read(vpd.raw, EMI_0_IO_BASE_ADDR, 0, 0, sizeof(vpd.raw));
20
21 /* If the magic value doesn't match, consider EEPROM VPD unreliable */
22 if (vpd.header.magic != VPD_MAGIC) {
23 printk(BIOS_WARNING, "Atlas VPD: Bad magic value, using fallback defaults\n");
24 vpd.header.revision = 0;
25 } else {
26 printk(BIOS_DEBUG, "Atlas VPD: Got revision %u from EC\n", vpd.header.revision);
27 }
28
29 /*
30 * For backwards compatibility, if the VPD from the EC is an older
31 * version, uprev it to the latest version coreboot knows about by
32 * filling in the remaining fields with default values. Should the
33 * EC provide a newer VPD revision, coreboot would downgrade it to
34 * the latest version it knows about as the VPD layout is designed
35 * to be backwards compatible.
36 *
37 * Whenever the value of `VPD_LATEST_REVISION` is incremented, add
38 * a new `case` label just before the `default` label that matches
39 * the second latest revision to initialise the newly-added fields
40 * of the VPD structure with a reasonable fallback value. Note the
41 * intentional falling through.
42 */
43 switch (vpd.header.revision) {
44 case 0:
45 memset(vpd.raw, 0, sizeof(vpd.raw));
46 vpd.header.magic = VPD_MAGIC;
47 vpd.serial_number[0] = '\0';
48 vpd.part_number[0] = '\0';
49 vpd.profile = ATLAS_PROF_UNPROGRAMMED;
50 __fallthrough;
51 default:
52 /* Ensure serial numbers are NULL-terminated, update revision last */
53 vpd.serial_number[ATLAS_SN_PN_LENGTH - 1] = '\0';
54 vpd.part_number[ATLAS_SN_PN_LENGTH - 1] = '\0';
55 vpd.header.revision = VPD_LATEST_REVISION;
56 break;
57 }
58
59 return &vpd;
60}