Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <console/console.h> |
Elyes Haouas | bdd03c2 | 2024-05-27 11:20:07 +0200 | [diff] [blame^] | 4 | #include <stdio.h> |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 5 | #include <string.h> |
| 6 | #include <types.h> |
| 7 | |
| 8 | #include "ec.h" |
| 9 | #include "mainboard.h" |
| 10 | #include "vpd.h" |
| 11 | |
Angel Pons | b327425 | 2023-05-10 21:57:45 +0200 | [diff] [blame] | 12 | static void write_invalid_str(char *dest, size_t length) |
| 13 | { |
| 14 | snprintf(dest, length, "%s", "INVALID"); |
| 15 | } |
| 16 | |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 17 | const struct emi_eeprom_vpd *get_emi_eeprom_vpd(void) |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 18 | { |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 19 | static union { |
| 20 | struct emi_eeprom_vpd layout; |
| 21 | uint8_t raw[sizeof(struct emi_eeprom_vpd)]; |
| 22 | } vpd = {0}; |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 23 | |
| 24 | /* Check if cached VPD is valid */ |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 25 | if (vpd.layout.header.revision == VPD_LATEST_REVISION) |
| 26 | return &vpd.layout; |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 27 | |
| 28 | ec_emi_read(vpd.raw, EMI_0_IO_BASE_ADDR, 0, 0, sizeof(vpd.raw)); |
| 29 | |
| 30 | /* If the magic value doesn't match, consider EEPROM VPD unreliable */ |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 31 | if (vpd.layout.header.magic != VPD_MAGIC) { |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 32 | printk(BIOS_WARNING, "Atlas VPD: Bad magic value, using fallback defaults\n"); |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 33 | vpd.layout.header.revision = 0; |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 34 | } else { |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 35 | printk(BIOS_DEBUG, "Atlas VPD: Got revision %u from EC\n", |
| 36 | vpd.layout.header.revision); |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 37 | } |
| 38 | |
| 39 | /* |
| 40 | * For backwards compatibility, if the VPD from the EC is an older |
| 41 | * version, uprev it to the latest version coreboot knows about by |
| 42 | * filling in the remaining fields with default values. Should the |
| 43 | * EC provide a newer VPD revision, coreboot would downgrade it to |
| 44 | * the latest version it knows about as the VPD layout is designed |
| 45 | * to be backwards compatible. |
| 46 | * |
| 47 | * Whenever the value of `VPD_LATEST_REVISION` is incremented, add |
| 48 | * a new `case` label just before the `default` label that matches |
| 49 | * the second latest revision to initialise the newly-added fields |
| 50 | * of the VPD structure with a reasonable fallback value. Note the |
| 51 | * intentional falling through. |
| 52 | */ |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 53 | switch (vpd.layout.header.revision) { |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 54 | case 0: |
| 55 | memset(vpd.raw, 0, sizeof(vpd.raw)); |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 56 | vpd.layout.header.magic = VPD_MAGIC; |
Angel Pons | b327425 | 2023-05-10 21:57:45 +0200 | [diff] [blame] | 57 | write_invalid_str(vpd.layout.serial_number, sizeof(vpd.layout.serial_number)); |
| 58 | write_invalid_str(vpd.layout.part_number, sizeof(vpd.layout.part_number)); |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 59 | vpd.layout.profile = ATLAS_PROF_UNPROGRAMMED; |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 60 | __fallthrough; |
| 61 | default: |
| 62 | /* Ensure serial numbers are NULL-terminated, update revision last */ |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 63 | vpd.layout.serial_number[ATLAS_SN_PN_LENGTH - 1] = '\0'; |
| 64 | vpd.layout.part_number[ATLAS_SN_PN_LENGTH - 1] = '\0'; |
| 65 | vpd.layout.header.revision = VPD_LATEST_REVISION; |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 66 | break; |
| 67 | } |
| 68 | |
Angel Pons | d4c5fc0 | 2023-03-27 12:06:08 +0200 | [diff] [blame] | 69 | return &vpd.layout; |
Angel Pons | 56c1c4d | 2023-03-22 13:25:09 +0100 | [diff] [blame] | 70 | } |