172 changes: 172 additions & 0 deletions src/commonlib/include/commonlib/tpm_log_serialized.h
@@ -0,0 +1,172 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __TPM_LOG_SERIALIZED_H__
#define __TPM_LOG_SERIALIZED_H__

#include <stdint.h>
#include <commonlib/helpers.h>

#define MAX_TCPA_LOG_ENTRIES 50
#define TCPA_DIGEST_MAX_LENGTH 64
#define TCPA_PCR_HASH_NAME 50
#define TCPA_PCR_HASH_LEN 10
/* Assumption of 2K TCPA log size reserved for CAR/SRAM */
#define MAX_PRERAM_TCPA_LOG_ENTRIES 15

struct tcpa_entry {
uint32_t pcr;
char digest_type[TCPA_PCR_HASH_LEN];
uint8_t digest[TCPA_DIGEST_MAX_LENGTH];
uint32_t digest_length;
char name[TCPA_PCR_HASH_NAME];
} __packed;

struct tcpa_table {
uint16_t max_entries;
uint16_t num_entries;
struct tcpa_entry entries[0]; /* Variable number of entries */
} __packed;

#define TCPA_SPEC_ID_EVENT_SIGNATURE "Spec ID Event00"

struct tcpa_log_entry {
uint32_t pcr;
uint32_t event_type;
uint8_t digest[20];
uint32_t event_data_size;
uint8_t event[0];
} __packed;

struct tcpa_spec_entry {
struct tcpa_log_entry entry;
uint8_t signature[16];
uint32_t platform_class;
uint8_t spec_version_minor;
uint8_t spec_version_major;
uint8_t spec_errata;
uint8_t reserved;
uint8_t vendor_info_size;
uint8_t vendor_info[0];
} __packed;

/* Some hardcoded algorithm values. */
/* Table 7 - TPM_ALG_ID Constants */
#define TPM2_ALG_ERROR 0x0000
#define TPM2_ALG_HMAC 0x0005
#define TPM2_ALG_NULL 0x0010
#define TPM2_ALG_SHA1 0x0004
#define TPM2_ALG_SHA256 0x000b
#define TPM2_ALG_SHA384 0x000c
#define TPM2_ALG_SHA512 0x000d
#define TPM2_ALG_SM3_256 0x0012

/* Annex A Algorithm Constants */

/* Table 205 - Defines for SHA1 Hash Values */
#define SHA1_DIGEST_SIZE 20
/* Table 206 - Defines for SHA256 Hash Values */
#define SHA256_DIGEST_SIZE 32
/* Table 207 - Defines for SHA384 Hash Values */
#define SHA384_DIGEST_SIZE 48
/* Table 208 - Defines for SHA512 Hash Values */
#define SHA512_DIGEST_SIZE 64
/* Table 209 - Defines for SM3_256 Hash Values */
#define SM3_256_DIGEST_SIZE 32

#define HASH_COUNT 2

/* Table 66 - TPMU_HA Union */
typedef union {
uint8_t sha1[SHA1_DIGEST_SIZE];
uint8_t sha256[SHA256_DIGEST_SIZE];
uint8_t sm3_256[SM3_256_DIGEST_SIZE];
uint8_t sha384[SHA384_DIGEST_SIZE];
uint8_t sha512[SHA512_DIGEST_SIZE];
} tpm_hash_digest;

typedef struct {
uint16_t hashAlg;
tpm_hash_digest digest;
} tpm_hash_algorithm;

/* Table 96 -- TPML_DIGEST_VALUES Structure <I/O> */
typedef struct {
uint32_t count;
tpm_hash_algorithm digests[HASH_COUNT];
} tpm_digest_values;

typedef struct {
uint16_t alg_id;
uint16_t digest_size;
} __packed tpm_digest_sizes;

typedef struct {
uint32_t pcr_index;
uint32_t event_type;
tpm_digest_values digest;
uint32_t event_size;
uint8_t event[0];
} __packed tcg_pcr_event2_header;

typedef struct {
uint32_t pcr_index;
uint32_t event_type;
uint8_t digest[20];
uint32_t event_size;
uint8_t signature[16];
uint32_t platform_class;
uint8_t spec_version_minor;
uint8_t spec_version_major;
uint8_t spec_errata;
uint8_t uintn_size;
uint32_t num_of_algorithms;
tpm_digest_sizes digest_sizes[HASH_COUNT];
uint8_t vendor_info_size;
uint8_t vendor_info[0];
} __packed tcg_efi_spec_id_event;

#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE "Spec ID Event03"

#define EV_PREBOOT_CERT 0x00000000
#define EV_POST_CODE 0x00000001
#define EV_UNUSED 0x00000002
#define EV_NO_ACTION 0x00000003
#define EV_SEPARATOR 0x00000004
#define EV_ACTION 0x00000005
#define EV_EVENT_TAG 0x00000006
#define EV_S_CRTM_CONTENTS 0x00000007
#define EV_S_CRTM_VERSION 0x00000008
#define EV_CPU_MICROCODE 0x00000009
#define EV_PLATFORM_CONFIG_FLAGS 0x0000000A
#define EV_TABLE_OF_DEVICES 0x0000000B
#define EV_COMPACT_HASH 0x0000000C
#define EV_IPL 0x0000000D
#define EV_IPL_PARTITION_DATA 0x0000000E
#define EV_NONHOST_CODE 0x0000000F
#define EV_NONHOST_CONFIG 0x00000010
#define EV_NONHOST_INFO 0x00000011
#define EV_OMIT_BOOT_DEVICE_EVENTS 0x00000012

static const char *tpm_event_types[] __unused = {
[EV_PREBOOT_CERT] = "Reserved",
[EV_POST_CODE] = "POST code",
[EV_UNUSED] = "Unused",
[EV_NO_ACTION] = "No action",
[EV_SEPARATOR] = "Separator",
[EV_ACTION] = "Action",
[EV_EVENT_TAG] = "Event tag",
[EV_S_CRTM_CONTENTS] = "S-CRTM contents",
[EV_S_CRTM_VERSION] = "S-CRTM version",
[EV_CPU_MICROCODE] = "CPU microcode",
[EV_PLATFORM_CONFIG_FLAGS] = "Platform configuration flags",
[EV_TABLE_OF_DEVICES] = "Table of devices",
[EV_COMPACT_HASH] = "Compact hash",
[EV_IPL] = "IPL",
[EV_IPL_PARTITION_DATA] = "IPL partition data",
[EV_NONHOST_CODE] = "Non-host code",
[EV_NONHOST_CONFIG] = "Non-host configuration",
[EV_NONHOST_INFO] = "Non-host information",
[EV_OMIT_BOOT_DEVICE_EVENTS] = "Omit boot device events",
};

#endif
6 changes: 4 additions & 2 deletions src/console/Makefile.inc
Expand Up @@ -11,12 +11,14 @@ smm-$(CONFIG_DEBUG_SMI) += init.c console.c vtxprintf.c printk.c
smm-y += die.c
smm-y += post.c

verstage-y += init.c
ifneq ($(CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK),y)
verstage-y += printk.c
verstage-y += vtxprintf.c vsprintf.c
verstage-y += console.c
endif
verstage-y += post.c
verstage-y += die.c
verstage-y += init.c
verstage-y += vtxprintf.c vsprintf.c

romstage-y += vtxprintf.c printk.c vsprintf.c
romstage-y += init.c console.c
Expand Down
2 changes: 1 addition & 1 deletion src/console/init.c
Expand Up @@ -67,7 +67,7 @@ asmlinkage void console_init(void)
if (CONFIG(DEBUG_CONSOLE_INIT))
console_inited = 1;

if (CONFIG(EARLY_PCI_BRIDGE) && !ENV_SMM && !ENV_RAMSTAGE)
if (CONFIG(EARLY_PCI_BRIDGE) && (ENV_BOOTBLOCK || ENV_ROMSTAGE))
pci_early_bridge_init();

console_hw_init();
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/amd/agesa/Kconfig
Expand Up @@ -16,8 +16,8 @@ config CPU_AMD_AGESA
select LAPIC_MONOTONIC_TIMER
select SPI_FLASH if HAVE_ACPI_RESUME
select SMM_ASEG
select NO_FIXED_XIP_ROM_SIZE
select SSE2
select ACPI_NO_SMI_GNVS

if CPU_AMD_AGESA

Expand Down
1 change: 0 additions & 1 deletion src/cpu/amd/pi/00730F01/Makefile.inc
Expand Up @@ -6,7 +6,6 @@ ramstage-y += fixme.c
ramstage-y += chip_name.c
ramstage-y += model_16_init.c
ramstage-y += update_microcode.c
ramstage-y += microcode_fam16h.c

subdirs-y += ../../mtrr
subdirs-y += ../../../x86/tsc
Expand Down
129 changes: 0 additions & 129 deletions src/cpu/amd/pi/00730F01/microcode_fam16h.c

This file was deleted.

2 changes: 1 addition & 1 deletion src/cpu/amd/pi/00730F01/model_16_init.c
Expand Up @@ -87,7 +87,7 @@ static void model_16_init(struct device *dev)
msr.lo |= (1 << 0);
wrmsr(HWCR_MSR, msr);

update_microcode(cpuid_eax(1));
amd_update_microcode_from_cbfs();
}

static struct device_operations cpu_dev_ops = {
Expand Down
141 changes: 115 additions & 26 deletions src/cpu/amd/pi/00730F01/update_microcode.c
Expand Up @@ -2,42 +2,131 @@

#include <stdint.h>
#include <cpu/amd/microcode.h>
#include <commonlib/helpers.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/msr.h>
#include <cbfs.h>

struct id_mapping {
uint32_t orig_id;
uint16_t new_id;
};
/*
* Values and header structure from:
* BKDG for AMD Family 16h Models 30h-3Fh Processors
* 52740 Rev 3.06 - March 18, 2016
*/

static u16 get_equivalent_processor_rev_id(u32 orig_id)
#define F16H_MPB_MAX_SIZE 3458
#define F16H_MPB_DATA_OFFSET 32

/*
* STRUCTURE OF A MICROCODE (UCODE) FILE FOR FAM16h
* Microcode Patch Block
* Microcode Header
* Microcode "Blob"
* ...
* ...
* (end of file)
*
*
* MICROCODE HEADER (offset 0 bytes from start of file)
* Total size = 32 bytes
* [0:3] Date code (32 bits)
* [4:7] Patch level (32 bits)
* [8:9] Microcode patch data ID (16 bits)
* [10:15] Reserved (48 bits)
* [16:19] Chipset 1 device ID (32 bits)
* [20:23] Chipset 2 device ID (32 bits)
* [24:25] Processor Revisions ID (16 bits)
* [26] Chipset 1 revision ID (8 bits)
* [27] Chipset 2 revision ID (8 bits)
* [28:31] Reserved (32 bits)
*
* MICROCODE BLOB (offset += 32)
* Total size = m bytes
*
*/

struct microcode {
uint32_t date_code;
uint32_t patch_id;

uint16_t mc_patch_data_id;
uint8_t reserved1[6];

uint32_t chipset1_dev_id;
uint32_t chipset2_dev_id;

uint16_t processor_rev_id;

uint8_t chipset1_rev_id;
uint8_t chipset2_rev_id;

uint8_t reserved2[4];

uint8_t m_patch_data[F16H_MPB_MAX_SIZE-F16H_MPB_DATA_OFFSET];
} __packed;

static void apply_microcode_patch(const struct microcode *m)
{
static const struct id_mapping id_mapping_table[] = {
/* Family 16h */
uint32_t new_patch_id;
msr_t msr;

/* TODO This equivalent processor revisions ID needs verification */
{ 0x730f01, 0x7301 },
msr.hi = (uint64_t)(uintptr_t)m >> 32;
msr.lo = (uintptr_t)m & 0xffffffff;

/* Array terminator */
{ 0xffffff, 0x0000 },
};
wrmsr(MSR_PATCH_LOADER, msr);

u32 new_id;
int i;
printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n",
m->patch_id);

new_id = 0;
msr = rdmsr(MSR_PATCH_LEVEL);
new_patch_id = msr.lo;

for (i = 0; id_mapping_table[i].orig_id != 0xffffff; i++) {
if (id_mapping_table[i].orig_id == orig_id) {
new_id = id_mapping_table[i].new_id;
break;
}
}
if (new_patch_id == m->patch_id)
printk(BIOS_INFO, "microcode: being updated to patch id = 0x%08x succeeded\n",
new_patch_id);
else
printk(BIOS_ERR, "microcode: being updated to patch id = 0x%08x failed\n",
new_patch_id);
}

return new_id;
static uint16_t get_equivalent_processor_rev_id(void)
{
uint32_t cpuid_family = cpuid_eax(1);

return (uint16_t)((cpuid_family & 0xff0000) >> 8 | (cpuid_family & 0xff));
}

static void amd_update_microcode(const void *ucode, size_t ucode_len,
uint16_t equivalent_processor_rev_id)
{
const struct microcode *m;
const uint8_t *c = ucode;

m = (struct microcode *)c;

/* Assume cpu_microcode_blob only contains one microcode. */
if (m->processor_rev_id == equivalent_processor_rev_id)
apply_microcode_patch(m);
}

void update_microcode(u32 cpu_deviceid)
void amd_update_microcode_from_cbfs(void)
{
u32 equivalent_processor_rev_id =
get_equivalent_processor_rev_id(cpu_deviceid);
amd_update_microcode_from_cbfs(equivalent_processor_rev_id);
const void *ucode;
size_t ucode_len;
uint16_t equivalent_processor_rev_id = get_equivalent_processor_rev_id();

ucode = cbfs_boot_map_with_leak("cpu_microcode_blob.bin",
CBFS_TYPE_MICROCODE, &ucode_len);
if (!ucode) {
printk(BIOS_WARNING, "cpu_microcode_blob.bin not found. Skipping updates.\n");
return;
}

if (ucode_len > F16H_MPB_MAX_SIZE ||
ucode_len < F16H_MPB_DATA_OFFSET) {
printk(BIOS_DEBUG, "microcode file invalid. Skipping updates.\n");
return;
}

amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id);
}
2 changes: 1 addition & 1 deletion src/cpu/amd/pi/Kconfig
Expand Up @@ -16,8 +16,8 @@ config CPU_AMD_PI
select LAPIC_MONOTONIC_TIMER
select SPI_FLASH if HAVE_ACPI_RESUME
select SMM_ASEG
select NO_FIXED_XIP_ROM_SIZE
select SSE2
select ACPI_NO_SMI_GNVS

if CPU_AMD_PI

Expand Down
1 change: 0 additions & 1 deletion src/cpu/amd/smm/smm_init.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <cpu/x86/lapic.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <cpu/amd/mtrr.h>
Expand Down
31 changes: 11 additions & 20 deletions src/cpu/intel/car/core2/cache_as_ram.S
Expand Up @@ -4,14 +4,6 @@
#include <cpu/x86/cache.h>
#include <cpu/x86/post_code.h>

#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE
#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE

#if ((CONFIG_C_ENV_BOOTBLOCK_SIZE & (CONFIG_C_ENV_BOOTBLOCK_SIZE - 1)) != 0)
#error "CONFIG_C_ENV_BOOTBLOCK_SIZE must be a power of 2!"
#endif
#define XIP_ROM_SIZE CONFIG_C_ENV_BOOTBLOCK_SIZE

.global bootblock_pre_c_entry

.code32
Expand Down Expand Up @@ -90,15 +82,17 @@ addrsize_set_high:
post_code(0x23)
/* Set Cache-as-RAM base address. */
movl $(MTRR_PHYS_BASE(0)), %ecx
movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
movl $_car_mtrr_start, %eax
orl $MTRR_TYPE_WRBACK, %eax
xorl %edx, %edx
wrmsr

post_code(0x24)
/* Set Cache-as-RAM mask. */
movl $(MTRR_PHYS_MASK(0)), %ecx
rdmsr
movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_car_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

post_code(0x25)
Expand All @@ -122,10 +116,11 @@ addrsize_set_high:
movl %eax, %cr0

/* Clear the cache memory region. This will also fill up the cache. */
movl $CACHE_AS_RAM_BASE, %esi
movl %esi, %edi
movl $(CACHE_AS_RAM_SIZE >> 2), %ecx
cld
xorl %eax, %eax
movl $_car_mtrr_start, %edi
movl $_car_mtrr_size, %ecx
shr $2, %ecx
rep stosl

post_code(0x26)
Expand All @@ -137,18 +132,14 @@ addrsize_set_high:
/* Enable cache for our code in Flash because we do XIP here */
movl $MTRR_PHYS_BASE(1), %ecx
xorl %edx, %edx
/*
* IMPORTANT: The following calculation _must_ be done at runtime. See
* https://mail.coreboot.org/pipermail/coreboot/2010-October/060922.html
*/
movl $_program, %eax
andl $(~(XIP_ROM_SIZE - 1)), %eax
andl $_xip_mtrr_mask, %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr

movl $MTRR_PHYS_MASK(1), %ecx
rdmsr
movl $(~(XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_xip_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

post_code(0x28)
Expand Down
23 changes: 12 additions & 11 deletions src/cpu/intel/car/non-evict/cache_as_ram.S
Expand Up @@ -4,10 +4,6 @@
#include <cpu/x86/cache.h>
#include <cpu/x86/post_code.h>

#define CACHE_AS_RAM_SIZE (CONFIG_DCACHE_RAM_SIZE \
+ CONFIG_DCACHE_RAM_MRC_VAR_SIZE)
#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE

#define NoEvictMod_MSR 0x2e0
#define BBL_CR_CTL3_MSR 0x11e

Expand Down Expand Up @@ -91,26 +87,30 @@ addrsize_set_high:
post_code(0x23)
/* Set Cache-as-RAM base address. */
movl $(MTRR_PHYS_BASE(0)), %ecx
movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
movl $_car_mtrr_start, %eax
orl $MTRR_TYPE_WRBACK, %eax
xorl %edx, %edx
wrmsr

post_code(0x24)
/* Set Cache-as-RAM mask. */
movl $(MTRR_PHYS_MASK(0)), %ecx
rdmsr
movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_car_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

/* Enable cache for our code in Flash because we do XIP here */
movl $MTRR_PHYS_BASE(1), %ecx
xorl %edx, %edx
movl $(CACHE_ROM_BASE | MTRR_TYPE_WRPROT), %eax
movl $_rom_mtrr_base, %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr

movl $MTRR_PHYS_MASK(1), %ecx
rdmsr
movl $(~(CACHE_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_rom_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

post_code(0x25)
Expand Down Expand Up @@ -171,10 +171,11 @@ end_microcode_update:
wrmsr

/* Clear the cache memory region. This will also fill up the cache. */
movl $CACHE_AS_RAM_BASE, %esi
movl %esi, %edi
movl $(CACHE_AS_RAM_SIZE >> 2), %ecx
cld
xorl %eax, %eax
movl $_car_mtrr_start, %edi
movl $_car_mtrr_size, %ecx
shr $2, %ecx
rep stosl

/* enable the 'no eviction run' state */
Expand Down
34 changes: 13 additions & 21 deletions src/cpu/intel/car/p3/cache_as_ram.S
Expand Up @@ -4,14 +4,6 @@
#include <cpu/x86/cache.h>
#include <cpu/x86/post_code.h>

#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE
#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE

#if ((CONFIG_C_ENV_BOOTBLOCK_SIZE & (CONFIG_C_ENV_BOOTBLOCK_SIZE - 1)) != 0)
#error "CONFIG_C_ENV_BOOTBLOCK_SIZE must be a power of 2!"
#endif
#define XIP_ROM_SIZE CONFIG_C_ENV_BOOTBLOCK_SIZE

.global bootblock_pre_c_entry

.code32
Expand Down Expand Up @@ -78,14 +70,16 @@ addrsize_set_high:

/* Set Cache-as-RAM base address. */
movl $(MTRR_PHYS_BASE(0)), %ecx
movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
movl $_car_mtrr_start, %eax
orl $MTRR_TYPE_WRBACK, %eax
xorl %edx, %edx
wrmsr

/* Set Cache-as-RAM mask. */
movl $(MTRR_PHYS_MASK(0)), %ecx
rdmsr
movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_car_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

post_code(0x2b)
Expand All @@ -107,12 +101,14 @@ addrsize_set_high:
/* Read then clear the CAR region. This will also fill up the cache.
* IMPORTANT: The read is mandatory.
*/
movl $CACHE_AS_RAM_BASE, %esi
movl %esi, %edi
cld
movl $(CACHE_AS_RAM_SIZE >> 2), %ecx
movl $_car_mtrr_start, %edi
movl $_car_mtrr_size, %ecx
shr $2, %ecx
movl %ecx, %ebx
movl %edi, %esi
rep lodsl
movl $(CACHE_AS_RAM_SIZE >> 2), %ecx
movl %ebx, %ecx
xorl %eax, %eax
rep stosl

Expand All @@ -125,18 +121,14 @@ addrsize_set_high:
/* Enable cache for our code in Flash because we do XIP here */
movl $MTRR_PHYS_BASE(1), %ecx
xorl %edx, %edx
/*
* IMPORTANT: The following calculation _must_ be done at runtime. See
* https://mail.coreboot.org/pipermail/coreboot/2010-October/060922.html
*/
movl $_program, %eax
andl $(~(XIP_ROM_SIZE - 1)), %eax
andl $_xip_mtrr_mask, %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr

movl $MTRR_PHYS_MASK(1), %ecx
rdmsr
movl $(~(XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_xip_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

post_code(0x2e)
Expand Down
36 changes: 14 additions & 22 deletions src/cpu/intel/car/p4-netburst/cache_as_ram.S
Expand Up @@ -8,14 +8,6 @@
/* Macro to access Local APIC registers at default base. */
#define LAPIC(x) $(LAPIC_DEFAULT_BASE | LAPIC_ ## x)

#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE
#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE

#if ((CONFIG_C_ENV_BOOTBLOCK_SIZE & (CONFIG_C_ENV_BOOTBLOCK_SIZE - 1)) != 0)
#error "CONFIG_C_ENV_BOOTBLOCK_SIZE must be a power of 2!"
#endif
#define XIP_ROM_SIZE CONFIG_C_ENV_BOOTBLOCK_SIZE

.global bootblock_pre_c_entry

.code32
Expand Down Expand Up @@ -219,14 +211,16 @@ sipi_complete:

/* Set Cache-as-RAM base address. */
movl $(MTRR_PHYS_BASE(0)), %ecx
movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
movl $_car_mtrr_start, %eax
orl $MTRR_TYPE_WRBACK, %eax
xorl %edx, %edx
wrmsr

/* Set Cache-as-RAM mask. */
movl $(MTRR_PHYS_MASK(0)), %ecx
rdmsr
movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_car_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

post_code(0x2b)
Expand Down Expand Up @@ -277,12 +271,13 @@ no_msr_11e:
/* Cache the whole rom to fetch microcode updates */
movl $MTRR_PHYS_BASE(1), %ecx
xorl %edx, %edx
movl $(CACHE_ROM_BASE | MTRR_TYPE_WRPROT), %eax
movl $_rom_mtrr_base, %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr

movl $MTRR_PHYS_MASK(1), %ecx
rdmsr
movl $(~(CACHE_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_rom_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

/* Enable cache (CR0.CD = 0, CR0.NW = 0). */
Expand Down Expand Up @@ -327,18 +322,14 @@ cache_rom:
/* Enable cache for our code in Flash because we do XIP here */
movl $MTRR_PHYS_BASE(1), %ecx
xorl %edx, %edx
/*
* IMPORTANT: The following calculation _must_ be done at runtime. See
* https://mail.coreboot.org/pipermail/coreboot/2010-October/060922.html
*/
movl $_program, %eax
andl $(~(XIP_ROM_SIZE - 1)), %eax
andl $_xip_mtrr_mask, %eax
orl $MTRR_TYPE_WRPROT, %eax
wrmsr

movl $MTRR_PHYS_MASK(1), %ecx
rdmsr
movl $(~(XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
movl $_xip_mtrr_mask, %eax
orl $MTRR_PHYS_MASK_VALID, %eax
wrmsr

fill_cache:
Expand All @@ -352,8 +343,9 @@ fill_cache:
/* Clear the cache memory region. This will also fill up the cache. */
cld
xorl %eax, %eax
movl $CACHE_AS_RAM_BASE, %edi
movl $(CACHE_AS_RAM_SIZE >> 2), %ecx
movl $_car_mtrr_start, %edi
movl $_car_mtrr_size, %ecx
shr $2, %ecx
rep stosl

/* Setup the stack. */
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/car/romstage.c
Expand Up @@ -4,7 +4,6 @@
#include <arch/romstage.h>
#include <bootblock_common.h>
#include <console/console.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/smm.h>
#include <arch/symbols.h>
#include <commonlib/helpers.h>
Expand Down
5 changes: 4 additions & 1 deletion src/cpu/intel/haswell/Kconfig
Expand Up @@ -22,7 +22,6 @@ config CPU_SPECIFIC_OPTIONS
select PARALLEL_MP
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select NO_FIXED_XIP_ROM_SIZE

config SMM_TSEG_SIZE
hex
Expand All @@ -35,4 +34,8 @@ config IED_REGION_SIZE
config SMM_RESERVED_SIZE
hex
default 0x100000

config MAX_CPUS
int
default 8
endif
1 change: 0 additions & 1 deletion src/cpu/intel/haswell/bootblock.c
Expand Up @@ -3,7 +3,6 @@
#include <stdint.h>
#include <arch/bootblock.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <arch/io.h>
#include <halt.h>

Expand Down
3 changes: 1 addition & 2 deletions src/cpu/intel/haswell/haswell_init.c
Expand Up @@ -13,7 +13,6 @@
#include <cpu/intel/speedstep.h>
#include <cpu/intel/turbo.h>
#include <cpu/x86/name.h>
#include <cpu/x86/smm.h>
#include <delay.h>
#include <northbridge/intel/haswell/haswell.h>
#include <southbridge/intel/lynxpoint/pch.h>
Expand Down Expand Up @@ -746,7 +745,7 @@ static void post_mp_init(void)
{
/* Now that all APs have been relocated as well as the BSP let SMIs
* start flowing. */
smm_southbridge_enable_smi();
global_smi_enable();

/* Lock down the SMRAM space. */
smm_lock();
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/haswell/romstage.c
Expand Up @@ -2,7 +2,6 @@

#include <console/console.h>
#include <cf9_reset.h>
#include <cpu/x86/bist.h>
#include <timestamp.h>
#include <cpu/x86/lapic.h>
#include <cbmem.h>
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/haswell/smmrelocate.c
Expand Up @@ -5,7 +5,6 @@
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/hyperthreading/intel_sibling.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <cpu/x86/lapic.h>
#include <cpu/intel/hyperthreading.h>
#include <device/device.h>
#include <option.h>
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_1067x/mp_init.c
Expand Up @@ -79,7 +79,7 @@ static void post_mp_init(void)
{
/* Now that all APs have been relocated as well as the BSP let SMIs
* start flowing. */
smm_southbridge_enable_smi();
global_smi_enable();

/* Lock down the SMRAM space. */
smm_lock();
Expand Down
5 changes: 4 additions & 1 deletion src/cpu/intel/model_2065x/Kconfig
Expand Up @@ -19,7 +19,6 @@ config CPU_SPECIFIC_OPTIONS
select TSC_SYNC_MFENCE
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select NO_FIXED_XIP_ROM_SIZE
select PARALLEL_MP

config SMM_TSEG_SIZE
Expand All @@ -30,4 +29,8 @@ config SMM_RESERVED_SIZE
hex
default 0x100000

config MAX_CPUS
int
default 4

endif
4 changes: 2 additions & 2 deletions src/cpu/intel/model_2065x/model_2065x_init.c
Expand Up @@ -228,7 +228,7 @@ static void model_2065x_init(struct device *cpu)
/* Print processor name */
fill_processor_name(processor_name);
printk(BIOS_INFO, "CPU: %s.\n", processor_name);
printk(BIOS_INFO, "CPU:lapic=%ld, boot_cpu=%d\n", lapicid(),
printk(BIOS_INFO, "CPU:lapic=%d, boot_cpu=%d\n", lapicid(),
boot_cpu());

/* Setup Page Attribute Tables (PAT) */
Expand Down Expand Up @@ -302,7 +302,7 @@ static void post_mp_init(void)
{
/* Now that all APs have been relocated as well as the BSP let SMIs
* start flowing. */
smm_southbridge_enable_smi();
global_smi_enable();

/* Lock down the SMRAM space. */
smm_lock();
Expand Down
5 changes: 4 additions & 1 deletion src/cpu/intel/model_206ax/Kconfig
Expand Up @@ -20,7 +20,6 @@ config CPU_SPECIFIC_OPTIONS
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select PARALLEL_MP
select NO_FIXED_XIP_ROM_SIZE

config SMM_TSEG_SIZE
hex
Expand All @@ -35,4 +34,8 @@ config IED_REGION_SIZE
hex
default 0x400000

config MAX_CPUS
int
default 8

endif
2 changes: 1 addition & 1 deletion src/cpu/intel/model_206ax/model_206ax_init.c
Expand Up @@ -528,7 +528,7 @@ static void post_mp_init(void)
{
/* Now that all APs have been relocated as well as the BSP let SMIs
* start flowing. */
smm_southbridge_enable_smi();
global_smi_enable();

/* Lock down the SMRAM space. */
smm_lock();
Expand Down
1 change: 1 addition & 0 deletions src/cpu/intel/slot_1/Kconfig
Expand Up @@ -32,6 +32,7 @@ config DCACHE_BSP_STACK_SIZE

config C_ENV_BOOTBLOCK_SIZE
hex
default 0x4000 if BOOTBLOCK_CONSOLE
default 0x2000

endif
4 changes: 4 additions & 0 deletions src/cpu/intel/socket_BGA956/Kconfig
Expand Up @@ -18,4 +18,8 @@ config DCACHE_BSP_STACK_SIZE
hex
default 0x2000

config MAX_CPUS
int
default 2

endif
5 changes: 4 additions & 1 deletion src/cpu/intel/socket_FCBGA559/Kconfig
Expand Up @@ -11,7 +11,6 @@ config SOCKET_SPECIFIC_OPTIONS
select MMX
select SSE
select CPU_HAS_L2_ENABLE_MSR
select NO_FIXED_XIP_ROM_SIZE

config DCACHE_RAM_BASE
hex
Expand All @@ -28,4 +27,8 @@ config DCACHE_BSP_STACK_SIZE
The amount of anticipated stack usage in CAR by bootblock and
other stages.

config MAX_CPUS
int
default 4

endif
4 changes: 4 additions & 0 deletions src/cpu/intel/socket_p/Kconfig
Expand Up @@ -19,4 +19,8 @@ config DCACHE_BSP_STACK_SIZE
hex
default 0x2000

config MAX_CPUS
int
default 4

endif
8 changes: 8 additions & 0 deletions src/cpu/ti/am335x/Kconfig
Expand Up @@ -8,3 +8,11 @@ config CPU_TI_AM335X
select BOOT_DEVICE_NOT_SPI_FLASH
bool
default n

if CPU_TI_AM335X

config MEMLAYOUT_LD_FILE
string
default "src/cpu/ti/am335x/memlayout.ld"

endif
5 changes: 1 addition & 4 deletions src/cpu/ti/am335x/Makefile.inc
Expand Up @@ -49,8 +49,5 @@ $(obj)/MLO: $(obj)/coreboot.rom $(obj)/omap-header.bin

omap-header-y += header.c

bootblock-y += memlayout.ld
romstage-y += memlayout.ld
ramstage-y += memlayout.ld
omap-header-y += memlayout.ld
omap-header-srcs += $(CONFIG_MEMLAYOUT_LD_FILE)
omap-header-y += header.ld
15 changes: 0 additions & 15 deletions src/cpu/x86/Kconfig
Expand Up @@ -60,21 +60,6 @@ config TSC_SYNC_MFENCE
to execute an mfence instruction in order to synchronize
rdtsc. This is true for all modern Intel CPUs.

config NO_FIXED_XIP_ROM_SIZE
bool
default n
help
The XIP_ROM_SIZE Kconfig variable is used globally on x86
with the assumption that all chipsets utilize this value.
For the chipsets which do not use the variable it can lead
to unnecessary alignment constraints in cbfs for romstage.
Therefore, allow those chipsets a path to not be burdened.

config XIP_ROM_SIZE
hex
depends on !NO_FIXED_XIP_ROM_SIZE
default 0x10000

config SETUP_XIP_CACHE
bool
depends on !NO_XIP_EARLY_STAGES
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/lapic/Makefile.inc
Expand Up @@ -6,7 +6,7 @@ romstage-$(CONFIG_UDELAY_LAPIC) += apic_timer.c
ramstage-$(CONFIG_UDELAY_LAPIC) += apic_timer.c
postcar-$(CONFIG_UDELAY_LAPIC) += apic_timer.c
bootblock-y += boot_cpu.c
verstage-y += boot_cpu.c
verstage_x86-y += boot_cpu.c
romstage-y += boot_cpu.c
ramstage-y += boot_cpu.c
postcar-y += boot_cpu.c
2 changes: 1 addition & 1 deletion src/cpu/x86/lapic/lapic.c
Expand Up @@ -47,6 +47,6 @@ void do_lapic_init(void)
LAPIC_DELIVERY_MODE_NMI)
);

printk(BIOS_DEBUG, " apic_id: 0x%02lx ", lapicid());
printk(BIOS_DEBUG, " apic_id: 0x%02x ", lapicid());
printk(BIOS_INFO, "done.\n");
}
8 changes: 4 additions & 4 deletions src/cpu/x86/lapic/lapic_cpu_init.c
Expand Up @@ -91,7 +91,7 @@ static void recover_lowest_1M(void)
static int lapic_start_cpu(unsigned long apicid)
{
int timeout;
unsigned long send_status, accept_status;
uint32_t send_status, accept_status;
int j, maxlvt;

/*
Expand Down Expand Up @@ -123,11 +123,11 @@ static int lapic_start_cpu(unsigned long apicid)
printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
"Disabling\n", apicid);
// too bad.
printk(BIOS_ERR, "ESR is 0x%lx\n", lapic_read(LAPIC_ESR));
printk(BIOS_ERR, "ESR is 0x%x\n", lapic_read(LAPIC_ESR));
if (lapic_read(LAPIC_ESR)) {
printk(BIOS_ERR, "Try to reset ESR\n");
lapic_write_around(LAPIC_ESR, 0);
printk(BIOS_ERR, "ESR is 0x%lx\n",
printk(BIOS_ERR, "ESR is 0x%x\n",
lapic_read(LAPIC_ESR));
}
return 0;
Expand Down Expand Up @@ -216,7 +216,7 @@ static int lapic_start_cpu(unsigned long apicid)
if (send_status)
printk(BIOS_WARNING, "APIC never delivered???\n");
if (accept_status)
printk(BIOS_WARNING, "APIC delivery error (%lx).\n",
printk(BIOS_WARNING, "APIC delivery error (%x).\n",
accept_status);
if (send_status || accept_status)
return 0;
Expand Down
1 change: 0 additions & 1 deletion src/cpu/x86/lapic/secondary.S
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <cpu/x86/mtrr.h>
#include <cpu/x86/lapic_def.h>
#include <arch/ram_segs.h>

Expand Down
4 changes: 2 additions & 2 deletions src/cpu/x86/mtrr/Makefile.inc
Expand Up @@ -2,12 +2,12 @@ ramstage-y += mtrr.c

romstage-y += earlymtrr.c
bootblock-y += earlymtrr.c
verstage-y += earlymtrr.c
verstage_x86-y += earlymtrr.c

bootblock-y += debug.c
romstage-y += debug.c
postcar-y += debug.c
ramstage-y += debug.c

bootblock-$(CONFIG_SETUP_XIP_CACHE) += xip_cache.c
verstage-$(CONFIG_SETUP_XIP_CACHE) += xip_cache.c
verstage_x86-$(CONFIG_SETUP_XIP_CACHE) += xip_cache.c
3 changes: 2 additions & 1 deletion src/cpu/x86/mtrr/debug.c
Expand Up @@ -92,8 +92,9 @@ static void display_mtrrcap(void)

msr = rdmsr(MTRR_CAP_MSR);
printk(BIOS_DEBUG,
"0x%08x%08x: IA32_MTRRCAP: %s%s%s%u variable MTRRs\n",
"0x%08x%08x: IA32_MTRRCAP: %s%s%s%s%u variable MTRRs\n",
msr.hi, msr.lo,
(msr.lo & MTRR_CAP_PRMRR) ? "PRMRR, " : "",
(msr.lo & MTRR_CAP_SMRR) ? "SMRR, " : "",
(msr.lo & MTRR_CAP_WC) ? "WC, " : "",
(msr.lo & MTRR_CAP_FIX) ? "FIX, " : "",
Expand Down
67 changes: 67 additions & 0 deletions src/cpu/x86/mtrr/earlymtrr.c
Expand Up @@ -65,3 +65,70 @@ void clear_all_var_mtrr(void)
wrmsr(MTRR_PHYS_BASE(i), mtrr);
}
}

void var_mtrr_context_init(struct var_mtrr_context *ctx, void *arg)
{
ctx->upper_mask = (1U << (cpu_phys_address_size() - 32)) - 1;
ctx->max_var_mtrrs = get_var_mtrr_count();
ctx->used_var_mtrrs = 0;
ctx->arg = arg;
}

int var_mtrr_set_with_cb(struct var_mtrr_context *ctx, uintptr_t addr, size_t size,
int type, void (*callback)(const struct var_mtrr_context *ctx,
uintptr_t base_addr, size_t size,
msr_t base, msr_t mask))
{
/* Utilize additional MTRRs if the specified size is greater than the
base address alignment. */
while (size != 0) {
uint32_t addr_lsb;
uint32_t size_msb;
uint32_t mtrr_size;
msr_t base;
msr_t mask;

if (ctx->used_var_mtrrs >= ctx->max_var_mtrrs) {
printk(BIOS_ERR, "No more variable MTRRs: %d\n",
ctx->max_var_mtrrs);
return -1;
}

addr_lsb = fls(addr);
size_msb = fms(size);

/* All MTRR entries need to have their base aligned to the mask
size. The maximum size is calculated by a function of the
min base bit set and maximum size bit set. */
if (addr_lsb > size_msb)
mtrr_size = 1 << size_msb;
else
mtrr_size = 1 << addr_lsb;

base.hi = (uint64_t)addr >> 32;
base.lo = addr | type;
mask.hi = ctx->upper_mask;
mask.lo = ~(mtrr_size - 1) | MTRR_PHYS_MASK_VALID;
callback(ctx, addr, mtrr_size, base, mask);
ctx->used_var_mtrrs++;

size -= mtrr_size;
addr += mtrr_size;
}

return 0;
}

static void set_mtrr(const struct var_mtrr_context *ctx, uintptr_t base_addr, size_t size,
msr_t base, msr_t mask)
{
int i = var_mtrr_context_current_mtrr(ctx);

wrmsr(MTRR_PHYS_BASE(i), base);
wrmsr(MTRR_PHYS_MASK(i), mask);
}

int var_mtrr_set(struct var_mtrr_context *ctx, uintptr_t addr, size_t size, int type)
{
return var_mtrr_set_with_cb(ctx, addr, size, type, set_mtrr);
}
19 changes: 15 additions & 4 deletions src/cpu/x86/mtrr/mtrr.c
Expand Up @@ -19,7 +19,6 @@
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/lapic.h>
#include <memrange.h>
#include <cpu/amd/mtrr.h>
#include <assert.h>
Expand Down Expand Up @@ -775,22 +774,34 @@ void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb)
commit_var_mtrrs(sol);
}

void x86_setup_mtrrs(void)
static void _x86_setup_mtrrs(unsigned int above4gb)
{
int address_size;

x86_setup_fixed_mtrrs();
address_size = cpu_phys_address_size();
printk(BIOS_DEBUG, "CPU physical address size: %d bits\n",
address_size);
x86_setup_var_mtrrs(address_size, above4gb);
}

void x86_setup_mtrrs(void)
{
/* Always handle addresses above 4GiB. */
x86_setup_var_mtrrs(address_size, 1);
_x86_setup_mtrrs(1);
}

void x86_setup_mtrrs_with_detect(void)
{
detect_var_mtrrs();
x86_setup_mtrrs();
/* Always handle addresses above 4GiB. */
_x86_setup_mtrrs(1);
}

void x86_setup_mtrrs_with_detect_no_above_4gb(void)
{
detect_var_mtrrs();
_x86_setup_mtrrs(0);
}

void x86_mtrr_check(void)
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/pae/Makefile.inc
@@ -1,5 +1,5 @@
bootblock-y += pgtbl.c
verstage-y += pgtbl.c
verstage_x86-y += pgtbl.c
romstage-y += pgtbl.c
postcar-y += pgtbl.c
ramstage-y += pgtbl.c
Expand Down
1 change: 1 addition & 0 deletions src/cpu/x86/smm/Makefile.inc
@@ -1,6 +1,7 @@
## SPDX-License-Identifier: GPL-2.0-only

ramstage-y += smm_module_loader.c
ramstage-y += smi_trigger.c

ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
$(eval $(call create_class_compiler,smm,x86_32))
Expand Down
76 changes: 76 additions & 0 deletions src/cpu/x86/smm/smi_trigger.c
@@ -0,0 +1,76 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi_gnvs.h>
#include <arch/io.h>
#include <console/console.h>
#include <cpu/x86/smm.h>

static void set_smm_gnvs_ptr(void);

int apm_control(u8 cmd)
{
if (!CONFIG(HAVE_SMI_HANDLER))
return -1;

switch (cmd) {
case APM_CNT_CST_CONTROL:
break;
case APM_CNT_PST_CONTROL:
break;
case APM_CNT_ACPI_DISABLE:
printk(BIOS_DEBUG, "Disabling ACPI via APMC.\n");
break;
case APM_CNT_ACPI_ENABLE:
printk(BIOS_DEBUG, "Enabling ACPI via APMC.\n");
break;
case APM_CNT_GNVS_UPDATE:
set_smm_gnvs_ptr();
return 0;
case APM_CNT_FINALIZE:
printk(BIOS_DEBUG, "Finalizing SMM.\n");
break;
case APM_CNT_ELOG_GSMI:
break;
case APM_CNT_SMMSTORE:
break;
case APM_CNT_SMMINFO:
break;
default:
break;
}

/* Now raise the SMI. */
outb(cmd, APM_CNT);

printk(BIOS_DEBUG, "APMC done.\n");
return 0;
}

static void set_smm_gnvs_ptr(void)
{
uintptr_t gnvs_address;

if (CONFIG(ACPI_NO_SMI_GNVS)) {
printk(BIOS_WARNING, "%s() is not implemented\n", __func__);
return;
}

gnvs_address = (uintptr_t)acpi_get_gnvs();
if (!gnvs_address)
return;

/*
* Issue SMI to set the gnvs pointer in SMM.
*
* EAX = APM_CNT_GNVS_UPDATE
* EBX = gnvs pointer
* EDX = APM_CNT
*/
asm volatile (
"outb %%al, %%dx\n\t"
: /* ignore result */
: "a" (APM_CNT_GNVS_UPDATE),
"b" (gnvs_address),
"d" (APM_CNT)
);
}
10 changes: 9 additions & 1 deletion src/cpu/x86/smm/smihandler.c
Expand Up @@ -2,6 +2,7 @@

#include <arch/io.h>
#include <console/console.h>
#include <commonlib/region.h>
#include <cpu/x86/smm.h>
#include <cpu/x86/smi_deprecated.h>
#include <cpu/amd/amd64_save_state.h>
Expand Down Expand Up @@ -119,6 +120,13 @@ static inline void *smm_save_state(uintptr_t base, int arch_offset, int node)
return (void *)base;
}

bool smm_region_overlaps_handler(const struct region *r)
{
const struct region r_smm = {SMM_BASE, SMM_DEFAULT_SIZE};

return region_overlap(&r_smm, r);
}

/**
* @brief Interrupt handler for SMI#
*
Expand All @@ -129,7 +137,7 @@ void smi_handler(u32 smm_revision)
{
unsigned int node;
smm_state_save_area_t state_save;
u32 smm_base = 0xa0000; /* ASEG */
u32 smm_base = SMM_BASE; /* ASEG */

/* Are we ok to execute the handler? */
if (!smi_obtain_lock()) {
Expand Down
9 changes: 9 additions & 0 deletions src/cpu/x86/smm/smm_module_handler.c
Expand Up @@ -2,6 +2,7 @@

#include <arch/io.h>
#include <console/console.h>
#include <commonlib/region.h>
#include <cpu/x86/smm.h>
#include <rmodule.h>

Expand Down Expand Up @@ -103,6 +104,14 @@ void *smm_get_save_state(int cpu)
return base;
}

bool smm_region_overlaps_handler(const struct region *r)
{
const struct region r_smm = {smm_runtime->smbase, smm_runtime->smm_size};
const struct region r_aseg = {SMM_BASE, SMM_DEFAULT_SIZE};

return region_overlap(&r_smm, r) || region_overlap(&r_aseg, r);
}

asmlinkage void smm_handler_start(void *arg)
{
const struct smm_module_params *p;
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/tsc/Makefile.inc
@@ -1,6 +1,6 @@
bootblock-$(CONFIG_UDELAY_TSC) += delay_tsc.c
ramstage-$(CONFIG_UDELAY_TSC) += delay_tsc.c
romstage-$(CONFIG_UDELAY_TSC) += delay_tsc.c
verstage-$(CONFIG_UDELAY_TSC) += delay_tsc.c
verstage_x86-$(CONFIG_UDELAY_TSC) += delay_tsc.c
postcar-$(CONFIG_UDELAY_TSC) += delay_tsc.c
smm-$(CONFIG_UDELAY_TSC) += delay_tsc.c
22 changes: 15 additions & 7 deletions src/device/Kconfig
Expand Up @@ -401,12 +401,15 @@ config FRAMEBUFFER_VESA_MODE
default 0x118 if FRAMEBUFFER_VESA_MODE_USER
endif # FRAMEBUFFER_SET_VESA_MODE

config WANT_LINEAR_FRAMEBUFFER
bool
default y if CHROMEOS
default y if PAYLOAD_TIANOCORE

choice
prompt "Framebuffer mode"
default VBE_LINEAR_FRAMEBUFFER if HAVE_VBE_LINEAR_FRAMEBUFFER && CHROMEOS
default GENERIC_LINEAR_FRAMEBUFFER if HAVE_LINEAR_FRAMEBUFFER && CHROMEOS
default VBE_LINEAR_FRAMEBUFFER if HAVE_VBE_LINEAR_FRAMEBUFFER && PAYLOAD_TIANOCORE
default GENERIC_LINEAR_FRAMEBUFFER if HAVE_LINEAR_FRAMEBUFFER && PAYLOAD_TIANOCORE
default VBE_LINEAR_FRAMEBUFFER if HAVE_VBE_LINEAR_FRAMEBUFFER && WANT_LINEAR_FRAMEBUFFER
default GENERIC_LINEAR_FRAMEBUFFER if HAVE_LINEAR_FRAMEBUFFER && WANT_LINEAR_FRAMEBUFFER
default VGA_TEXT_FRAMEBUFFER

config VGA_TEXT_FRAMEBUFFER
Expand Down Expand Up @@ -776,10 +779,10 @@ config INTEL_GMA_ADD_VBT
config INTEL_GMA_VBT_FILE
string "VBT binary path and filename"
depends on INTEL_GMA_ADD_VBT
default "src/mainboard/$(MAINBOARDDIR)/variants/$(VARIANT_DIR)/data.vbt" \
default "src/mainboard/\$(MAINBOARDDIR)/variants/\$(VARIANT_DIR)/data.vbt" \
if INTEL_GMA_HAVE_VBT && VARIANT_DIR != ""
default "src/mainboard/$(MAINBOARDDIR)/data.vbt" if INTEL_GMA_HAVE_VBT
default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/vbt.bin"
default "src/mainboard/\$(MAINBOARDDIR)/data.vbt" if INTEL_GMA_HAVE_VBT
default "3rdparty/blobs/mainboard/\$(MAINBOARDDIR)/vbt.bin"
help
The path and filename of the VBT binary.

Expand Down Expand Up @@ -811,4 +814,9 @@ config RESOURCE_ALLOCATOR_V4
ranges for allocating resources. This allows allocation of resources
above 4G boundary as well.

config XHCI_UTILS
def_bool n
help
Provides xHCI utility functions.

endmenu
2 changes: 2 additions & 0 deletions src/device/Makefile.inc
Expand Up @@ -62,3 +62,5 @@ ramstage-y += mmio.c
ramstage-y += resource_allocator_common.c
ramstage-$(CONFIG_RESOURCE_ALLOCATOR_V3) += resource_allocator_v3.c
ramstage-$(CONFIG_RESOURCE_ALLOCATOR_V4) += resource_allocator_v4.c

ramstage-$(CONFIG_XHCI_UTILS) += xhci.c
6 changes: 1 addition & 5 deletions src/device/azalia_device.c
Expand Up @@ -241,14 +241,10 @@ void azalia_audio_init(struct device *dev)
}
}

struct pci_operations azalia_audio_pci_ops = {
.set_subsystem = pci_dev_set_subsystem,
};

struct device_operations default_azalia_audio_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = azalia_audio_init,
.ops_pci = &azalia_audio_pci_ops,
.ops_pci = &pci_dev_ops_pci,
};
4 changes: 2 additions & 2 deletions src/device/device.c
Expand Up @@ -12,7 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <smp/spinlock.h>
#if CONFIG(ARCH_X86)
#if ENV_X86
#include <arch/ebda.h>
#endif
#include <timer.h>
Expand Down Expand Up @@ -566,7 +566,7 @@ void dev_initialize(void)

printk(BIOS_INFO, "Initializing devices...\n");

#if CONFIG(ARCH_X86)
#if ENV_X86
/* Ensure EBDA is prepared before Option ROMs. */
setup_default_ebda();
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/device/oprom/include/io.h
Expand Up @@ -3,7 +3,7 @@
#ifndef __OPROM_IO_H__
#define __OPROM_IO_H__

#if CONFIG(ARCH_X86)
#if ENV_X86
#include <arch/io.h>
#else
void outb(u8 val, u16 port);
Expand Down
2 changes: 1 addition & 1 deletion src/device/oprom/yabel/compat/functions.c
Expand Up @@ -72,7 +72,7 @@ unsigned long tb_freq = 0;
u64 get_time(void)
{
u64 act = 0;
#if CONFIG(ARCH_X86)
#if ENV_X86
u32 eax, edx;

__asm__ __volatile__(
Expand Down
8 changes: 4 additions & 4 deletions src/device/oprom/yabel/device.h
Expand Up @@ -151,7 +151,7 @@ u8 biosemu_dev_translate_address(int type, unsigned long * addr);
static inline void
out32le(void *addr, u32 val)
{
#if CONFIG(ARCH_X86) || CONFIG(ARCH_ARM)
#if ENV_X86 || ENV_ARM || ENV_ARM64
*((u32*) addr) = cpu_to_le32(val);
#else
asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr));
Expand All @@ -162,7 +162,7 @@ static inline u32
in32le(void *addr)
{
u32 val;
#if CONFIG(ARCH_X86) || CONFIG(ARCH_ARM)
#if ENV_X86 || ENV_ARM || ENV_ARM64
val = cpu_to_le32(*((u32 *) addr));
#else
asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr));
Expand All @@ -173,7 +173,7 @@ in32le(void *addr)
static inline void
out16le(void *addr, u16 val)
{
#if CONFIG(ARCH_X86) || CONFIG(ARCH_ARM)
#if ENV_X86 || ENV_ARM || ENV_ARM64
*((u16*) addr) = cpu_to_le16(val);
#else
asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr));
Expand All @@ -184,7 +184,7 @@ static inline u16
in16le(void *addr)
{
u16 val;
#if CONFIG(ARCH_X86) || CONFIG(ARCH_ARM)
#if ENV_X86 || ENV_ARM || ENV_ARM64
val = cpu_to_le16(*((u16*) addr));
#else
asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr));
Expand Down
6 changes: 5 additions & 1 deletion src/device/pci_device.c
Expand Up @@ -11,7 +11,6 @@
#include <console/console.h>
#include <cpu/cpu.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <delay.h>
#include <device/cardbus.h>
Expand Down Expand Up @@ -1644,4 +1643,9 @@ void pci_assign_irqs(struct device *dev, const unsigned char pIntAtoD[4])
#endif
}
}

void pci_dev_disable_bus_master(const struct device *dev)
{
pci_update_config16(dev, PCI_COMMAND, ~PCI_COMMAND_MASTER, 0x0);
}
#endif
86 changes: 86 additions & 0 deletions src/device/xhci.c
@@ -0,0 +1,86 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <device/xhci.h>
#include <console/console.h>
#include <device/pci_def.h>
#include <arch/mmio.h>

union xhci_ext_caps_header {
uint32_t val;
struct {
uint32_t cap_id : 8;
uint32_t next_ptr : 8;
uint32_t reserved : 16;
};
};

enum cb_err xhci_for_each_ext_cap(const struct device *device, void *context,
void (*callback)(void *context,
const struct xhci_ext_cap *cap))
{
struct resource *res;
uint32_t *ext_cap_ptr;
uint32_t ext_caps_word_offset;
union xhci_ext_caps_header header;
struct xhci_ext_cap cap;

if (!device || !callback)
return CB_ERR_ARG;

res = probe_resource(device, PCI_BASE_ADDRESS_0);
if (!res) {
printk(BIOS_ERR, "%s: Unable to find BAR resource for %s\n", __func__,
dev_path(device));
return CB_ERR;
}

if (!(res->flags & IORESOURCE_ASSIGNED)) {
printk(BIOS_ERR, "%s: BAR is is not assigned\n", __func__);
return CB_ERR;
}

if (res->limit > 0xFFFFFFFF) {
printk(BIOS_ERR, "%s: 64-bit BAR is not supported\n", __func__);
return CB_ERR;
}

ext_caps_word_offset = read16(res2mmio(res, XHCI_HCCPARAMS1_XECP, 0));

if (!ext_caps_word_offset) {
printk(BIOS_ERR, "%s: No extended capabilities defined\n", __func__);
return CB_ERR;
}

ext_cap_ptr = res2mmio(res, ext_caps_word_offset << 2, 0);

while ((uintptr_t)ext_cap_ptr < (uintptr_t)res->limit) {
header.val = read32(ext_cap_ptr);

cap.cap_id = header.cap_id;

if (header.cap_id == XHCI_ECP_CAP_ID_SUPP) {
cap.supported_protocol.reg0 = header.val;
cap.supported_protocol.reg1 = read32(ext_cap_ptr + 1);
cap.supported_protocol.reg2 = read32(ext_cap_ptr + 2);
}

callback(context, &cap);

if (!header.next_ptr)
break;

ext_cap_ptr += header.next_ptr;
}

return CB_SUCCESS;
}

void xhci_print_supported_protocol(const struct xhci_supported_protocol *supported_protocol)
{
printk(BIOS_DEBUG, "xHCI Supported Protocol:\n");
printk(BIOS_DEBUG, " Major: %#x, Minor: %#x, Protocol: '%.*s'\n",
supported_protocol->major_rev, supported_protocol->minor_rev,
(int)sizeof(supported_protocol->name), supported_protocol->name);
printk(BIOS_DEBUG, " Port Offset: %d, Port Count: %d\n",
supported_protocol->port_offset, supported_protocol->port_count);
}
5 changes: 1 addition & 4 deletions src/drivers/amd/agesa/def_callouts.c
Expand Up @@ -12,12 +12,9 @@
#include <northbridge/amd/agesa/BiosCallOuts.h>
#include <northbridge/amd/agesa/dimmSpd.h>

#if CONFIG(NORTHBRIDGE_AMD_PI)
#if CONFIG(ARCH_ROMSTAGE_X86_64) || \
CONFIG(ARCH_RAMSTAGE_X86_64)
#if ENV_X86_64 && CONFIG(NORTHBRIDGE_AMD_PI)
#error "FIXME: CALLOUT_ENTRY is UINT32 Data, not UINT Data"
#endif
#endif

AGESA_STATUS GetBiosCallout (UINT32 Func, UINTN Data, VOID *ConfigPtr)
{
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/amd/agesa/mtrr_fixme.c
Expand Up @@ -59,7 +59,7 @@ void recover_postcar_frame(struct postcar_frame *pcf, int s3resume)

/* Replicate non-UC MTRRs as left behind by AGESA.
*/
for (i = 0; i < pcf->max_var_mtrrs; i++) {
for (i = 0; i < pcf->ctx.max_var_mtrrs; i++) {
mask = rdmsr(MTRR_PHYS_MASK(i));
base = rdmsr(MTRR_PHYS_BASE(i));
u32 size = ~(mask.lo & ~0xfff) + 1;
Expand Down
1 change: 0 additions & 1 deletion src/drivers/analogix/anx7625/anx7625.c
Expand Up @@ -5,7 +5,6 @@
#include <device/i2c_simple.h>
#include <edid.h>
#include <gpio.h>
#include <timer.h>
#include <string.h>

#include "anx7625.h"
Expand Down
8 changes: 1 addition & 7 deletions src/drivers/elog/elog.c
@@ -1,8 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#if CONFIG(HAVE_ACPI_RESUME)
#include <acpi/acpi.h>
#endif
#include <bootstate.h>
#include <cbmem.h>
#include <console/console.h>
Expand Down Expand Up @@ -738,17 +736,13 @@ static bool elog_do_add_boot_count(void)
if (ENV_SMM)
return false;

#if CONFIG(HAVE_ACPI_RESUME)
return !acpi_is_wakeup_s3();
#else
return true;
#endif
}

/* Check and log POST codes from previous boot */
static void log_last_boot_post(void)
{
#if CONFIG(ARCH_X86)
#if ENV_X86
u8 code;
u32 extra;

Expand Down
1 change: 0 additions & 1 deletion src/drivers/elog/gsmi.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <cpu/x86/smm.h>
#include <elog.h>

#define GSMI_RET_SUCCESS 0x00
Expand Down
6 changes: 1 addition & 5 deletions src/drivers/generic/bayhub/bh720.c
Expand Up @@ -46,15 +46,11 @@ static void bh720_init(struct device *dev)
board_bh720(dev);
}

static struct pci_operations pci_ops = {
.set_subsystem = pci_dev_set_subsystem,
};

static struct device_operations bh720_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.ops_pci = &pci_ops,
.ops_pci = &pci_dev_ops_pci,
.init = bh720_init,
};

Expand Down
8 changes: 4 additions & 4 deletions src/drivers/generic/max98357a/max98357a.c
Expand Up @@ -26,15 +26,15 @@ static void max98357a_fill_ssdt(const struct device *dev)
if (!scope || !name)
return;

/* Device */
acpigen_write_scope(scope);
acpigen_write_device(name);

if (!config->hid) {
printk(BIOS_ERR, "%s: ERROR: _HID required\n", dev_path(dev));
return;
}

/* Device */
acpigen_write_scope(scope);
acpigen_write_device(name);

acpigen_write_name_string("_HID", config->hid);
acpigen_write_name_integer("_UID", 0);
acpigen_write_name_string("_DDN", dev->chip_ops->name);
Expand Down
1 change: 0 additions & 1 deletion src/drivers/i2c/tpm/tpm.c
Expand Up @@ -17,7 +17,6 @@


#include <commonlib/endian.h>
#include <stdint.h>
#include <string.h>
#include <types.h>
#include <delay.h>
Expand Down
7 changes: 7 additions & 0 deletions src/drivers/intel/dptf/Kconfig
@@ -0,0 +1,7 @@
config DRIVERS_INTEL_DPTF
bool "Support runtime generation of Intel DPTF ACPI tables"
depends on HAVE_ACPI_TABLES
default n
help
When enabled, entries in the devicetree are used to generate
Intel DPTF Tables at runtime in the SSDT.
1 change: 1 addition & 0 deletions src/drivers/intel/dptf/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_INTEL_DPTF) += dptf.c
9 changes: 9 additions & 0 deletions src/drivers/intel/dptf/chip.h
@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef _DRIVERS_INTEL_DPTF_CHIP_H_
#define _DRIVERS_INTEL_DPTF_CHIP_H_

struct drivers_intel_dptf_config {
};

#endif /* _DRIVERS_INTEL_DPTF_CHIP_H_ */
56 changes: 56 additions & 0 deletions src/drivers/intel/dptf/dptf.c
@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpigen.h>
#include <console/console.h>
#include <device/device.h>
#include "chip.h"

static const char *dptf_acpi_name(const struct device *dev)
{
return "DPTF";
}

/* Add custom tables and methods to SSDT */
static void dptf_fill_ssdt(const struct device *dev)
{
struct drivers_intel_dptf_config *config = dev->chip_info;

printk(BIOS_INFO, "\\_SB.DPTF: %s at %s\n", dev->chip_ops->name, dev_path(dev));
}

/* Add static definitions of DPTF devices into the DSDT */
static void dptf_inject_dsdt(const struct device *dev)
{
const struct drivers_intel_dptf_config *config;

config = dev->chip_info;
acpigen_write_scope("\\_SB");

/* Toplevel DPTF device */
acpigen_write_device(acpi_device_name(dev));
acpigen_write_name("_HID");
acpigen_emit_eisaid("INT3400");
acpigen_write_name_integer("_UID", 0);
dptf_write_STA();

acpigen_pop_len(); /* DPTF Device */
acpigen_pop_len(); /* Scope */
}

static struct device_operations dptf_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.acpi_name = dptf_acpi_name,
.acpi_fill_ssdt = dptf_fill_ssdt,
.acpi_inject_dsdt = dptf_inject_dsdt,
};

static void dptf_enable_dev(struct device *dev)
{
dev->ops = &dptf_ops;
}

struct chip_operations drivers_intel_dptf_ops = {
CHIP_NAME("Intel DPTF")
.enable_dev = dptf_enable_dev,
};
2 changes: 1 addition & 1 deletion src/drivers/intel/fsp1_1/Kconfig
Expand Up @@ -88,6 +88,6 @@ config FSP1_1_DISPLAY_LOGO
config FSP1_1_LOGO_FILE_NAME
string "Logo file"
depends on FSP1_1_DISPLAY_LOGO
default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/logo.bmp"
default "3rdparty/blobs/mainboard/\$(MAINBOARDDIR)/logo.bmp"

endif #PLATFORM_USES_FSP1_1
1 change: 0 additions & 1 deletion src/drivers/intel/fsp1_1/car.c
Expand Up @@ -6,7 +6,6 @@
#include <console/console.h>
#include <commonlib/helpers.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/smm.h>
#include <fsp/car.h>
#include <fsp/util.h>
#include <program_loading.h>
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/fsp1_1/hob.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <arch/hlt.h>
#include <bootstate.h>
#include <console/console.h>
#include <fsp/util.h>
#include <ip_checksum.h>
Expand Down
2 changes: 0 additions & 2 deletions src/drivers/intel/fsp1_1/raminit.c
Expand Up @@ -145,12 +145,10 @@ void raminit(struct romstage_params *params)
fsp_reserved_bytes);
} else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
fsp_reserved_bytes)) {
#if CONFIG(HAVE_ACPI_RESUME)
printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n");
/* Failed S3 resume, reset to come up cleanly */
/* FIXME: A "system" reset is likely enough: */
full_reset();
#endif
}

/* Save the FSP runtime parameters. */
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/fsp1_1/ramstage.c
Expand Up @@ -3,7 +3,6 @@
#include <bootmode.h>
#include <acpi/acpi.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <fsp/ramstage.h>
#include <fsp/util.h>
#include <lib.h>
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/fsp1_1/romstage.c
Expand Up @@ -7,7 +7,6 @@
#include <cbmem.h>
#include <cf9_reset.h>
#include <cpu/intel/microcode.h>
#include <cpu/x86/mtrr.h>
#include <ec/google/chromeec/ec.h>
#include <ec/google/chromeec/ec_commands.h>
#include <elog.h>
Expand Down
25 changes: 18 additions & 7 deletions src/drivers/intel/fsp2_0/Kconfig
Expand Up @@ -11,12 +11,23 @@ config PLATFORM_USES_FSP2_1
default n
select PLATFORM_USES_FSP2_0
select FSP_USES_CB_STACK
select FSP_PEIM_TO_PEIM_INTERFACE
help
Include FSP 2.1 wrappers and functionality.
Features added into FSP 2.1 specification that impacts coreboot are:
Feature added into FSP 2.1 specification that impacts coreboot is:
1. Remove FSP stack switch and use the same stack with boot firmware
2. FSP should support external PPI interface pulled in via FSP_PEIM_TO_PEIM_INTERFACE

config PLATFORM_USES_FSP2_2
bool
default n
select PLATFORM_USES_FSP2_1
help
Include FSP 2.2 wrappers and functionality.
Features added into FSP 2.2 specification that impact coreboot are:
1. Added multi-phase silicon initialization to increase the modularity of the
FspSiliconInit() API
2. FSP_INFO_HEADER changes to add FspMultiPhaseSiInitEntryOffset
3. Added EnableMultiPhaseSiliconInit, bootloaders designed for FSP2.0/2.1 can disable
the FspMultiPhaseSiInit() API and continue to use FspSiliconInit() without change.

if PLATFORM_USES_FSP2_0

Expand Down Expand Up @@ -74,21 +85,21 @@ config FSP_T_FILE
string "Intel FSP-T (temp RAM init) binary path and filename" if !FSP_USE_REPO
depends on ADD_FSP_BINARIES
depends on FSP_CAR
default "$(obj)/Fsp_T.fd" if FSP_USE_REPO
default "\$(obj)/Fsp_T.fd" if FSP_USE_REPO
help
The path and filename of the Intel FSP-T binary for this platform.

config FSP_M_FILE
string "Intel FSP-M (memory init) binary path and filename" if !FSP_USE_REPO
depends on ADD_FSP_BINARIES
default "$(obj)/Fsp_M.fd" if FSP_USE_REPO
default "\$(obj)/Fsp_M.fd" if FSP_USE_REPO
help
The path and filename of the Intel FSP-M binary for this platform.

config FSP_S_FILE
string "Intel FSP-S (silicon init) binary path and filename" if !FSP_USE_REPO
depends on ADD_FSP_BINARIES
default "$(obj)/Fsp_S.fd" if FSP_USE_REPO
default "\$(obj)/Fsp_S.fd" if FSP_USE_REPO
help
The path and filename of the Intel FSP-S binary for this platform.

Expand Down Expand Up @@ -179,7 +190,7 @@ config FSP2_0_DISPLAY_LOGO
config FSP2_0_LOGO_FILE_NAME
string "Logo file"
depends on FSP2_0_DISPLAY_LOGO
default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/logo.bmp"
default "3rdparty/blobs/mainboard/\$(MAINBOARDDIR)/logo.bmp"

config FSP_COMPRESS_FSP_S_LZMA
bool
Expand Down
3 changes: 3 additions & 0 deletions src/drivers/intel/fsp2_0/header_display.c
Expand Up @@ -40,6 +40,9 @@ void fsp_print_header_info(const struct fsp_header *hdr)
if ((hdr->component_attribute >> 12) == FSP_HDR_ATTRIB_FSPS) {
printk(BIOS_SPEW, "\tSilicon init offset 0x%zx\n",
hdr->silicon_init_entry_offset);
if (CONFIG(PLATFORM_USES_FSP2_2))
printk(BIOS_SPEW, "\tMultiPhaseSiInit offset 0x%zx\n",
hdr->multi_phase_si_init_entry_offset);
printk(BIOS_SPEW, "\tNotify phase offset 0x%zx\n",
hdr->notify_phase_entry_offset);
}
Expand Down
5 changes: 4 additions & 1 deletion src/drivers/intel/fsp2_0/include/fsp/api.h
Expand Up @@ -47,7 +47,10 @@ void fsps_load(bool s3wake);
/* Callbacks for updating stage-specific parameters */
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version);
void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd);

/* Callbacks for SoC/Mainboard specific overrides */
void platform_fsp_multi_phase_init_cb(uint32_t phase_index);
/* Check if SoC sets EnableMultiPhaseSiliconInit UPD */
int soc_fsp_multi_phase_init_is_enable(void);
/*
* The following functions are used when FSP_PLATFORM_MEMORY_SETTINGS_VERSION
* is employed allowing the mainboard and SoC to supply their own version
Expand Down
6 changes: 5 additions & 1 deletion src/drivers/intel/fsp2_0/include/fsp/info_header.h
Expand Up @@ -3,11 +3,14 @@
#ifndef _FSP2_0_INFO_HEADER_H_
#define _FSP2_0_INFO_HEADER_H_

#include <stdint.h>
#include <types.h>

#define FSP_HDR_OFFSET 0x94
#if CONFIG(PLATFORM_USES_FSP2_2)
#define FSP_HDR_LEN 0x4c
#else
#define FSP_HDR_LEN 0x48
#endif
#define FSP_HDR_SIGNATURE "FSPH"
#define FSP_HDR_ATTRIB_FSPT 1
#define FSP_HDR_ATTRIB_FSPM 2
Expand All @@ -27,6 +30,7 @@ struct fsp_header {
size_t notify_phase_entry_offset;
size_t memory_init_entry_offset;
size_t silicon_init_entry_offset;
size_t multi_phase_si_init_entry_offset;
char image_id[sizeof(uint64_t) + 1];
uint8_t revision;
};
Expand Down
18 changes: 18 additions & 0 deletions src/drivers/intel/fsp2_0/include/fsp/upd.h
Expand Up @@ -54,4 +54,22 @@ struct FSPM_ARCH_UPD {
uint8_t Reserved1[8];
} __packed;

struct FSPS_ARCH_UPD {
///
/// Revision of the structure. For FSP v2.2 value is 1.
///
uint8_t Revision;
uint8_t Reserved[3];
///
/// Length of the structure in bytes. The current value for this field is 32
///
uint32_t Length;
uint8_t Reserved1[4];
///
/// To enable multi-phase silicon initialization the bootloader must set non-zero value
///
uint8_t EnableMultiPhaseSiliconInit;
uint8_t Reserved2[19];
} __packed;

#endif /* _FSP2_0_UPD_H_ */
12 changes: 12 additions & 0 deletions src/drivers/intel/fsp2_0/include/fsp/util.h
Expand Up @@ -21,6 +21,17 @@ struct fsp_notify_params {
enum fsp_notify_phase phase;
};

enum fsp_multi_phase_action {
GET_NUMBER_OF_PHASES = 0,
EXECUTE_PHASE = 1
};

struct fsp_multi_phase_params {
enum fsp_multi_phase_action multi_phase_action;
uint32_t phase_index;
void *multi_phase_param_ptr;
};

struct hob_resource {
uint8_t owner_guid[16];
uint32_t type;
Expand Down Expand Up @@ -115,6 +126,7 @@ typedef asmlinkage uint32_t (*temp_ram_exit_fn)(void *param);
typedef asmlinkage uint32_t (*fsp_memory_init_fn)
(void *raminit_upd, void **hob_list);
typedef asmlinkage uint32_t (*fsp_silicon_init_fn)(void *silicon_upd);
typedef asmlinkage uint32_t (*fsp_multi_phase_si_init_fn)(struct fsp_multi_phase_params *);
typedef asmlinkage uint32_t (*fsp_notify_fn)(struct fsp_notify_params *);
#include <fsp/debug.h>

Expand Down
19 changes: 10 additions & 9 deletions src/drivers/intel/fsp2_0/memory_init.c
Expand Up @@ -196,15 +196,6 @@ static enum cb_err fsp_fill_common_arch_params(FSPM_ARCH_UPD *arch_upd,

/* Configure bootmode */
if (s3wake) {
/*
* For S3 resume case, if valid mrc cache data is not found or
* RECOVERY_MRC_CACHE hash verification fails, the S3 data
* pointer would be null and S3 resume fails with fsp-m
* returning error. Invoking a reset here saves time.
*/
if (!arch_upd->NvsBufferPtr)
/* FIXME: A "system" reset is likely enough: */
full_reset();
arch_upd->BootMode = FSP_BOOT_ON_S3_RESUME;
} else {
if (arch_upd->NvsBufferPtr)
Expand Down Expand Up @@ -296,6 +287,16 @@ static void do_fsp_memory_init(const struct fspm_context *context, bool s3wake)
/* Give SoC and mainboard a chance to update the UPD */
platform_fsp_memory_init_params_cb(&fspm_upd, fsp_version);

/*
* For S3 resume case, if valid mrc cache data is not found or
* RECOVERY_MRC_CACHE hash verification fails, the S3 data
* pointer would be null and S3 resume fails with fsp-m
* returning error. Invoking a reset here saves time.
*/
if (s3wake && !arch_upd->NvsBufferPtr)
/* FIXME: A "system" reset is likely enough: */
full_reset();

if (CONFIG(MMA))
setup_mma(&fspm_upd.FspmConfig);

Expand Down
116 changes: 103 additions & 13 deletions src/drivers/intel/fsp2_0/silicon_init.c
Expand Up @@ -16,13 +16,74 @@

struct fsp_header fsps_hdr;

struct fsp_multi_phase_get_number_of_phases_params {
uint32_t number_of_phases;
uint32_t phases_executed;
};

/* Callbacks for SoC/Mainboard specific overrides */
void __weak platform_fsp_multi_phase_init_cb(uint32_t phase_index)
{
/* Leave for the SoC/Mainboard to implement if necessary. */
}

int __weak soc_fsp_multi_phase_init_is_enable(void)
{
return 1;
}

/* FSP Specification < 2.2 has only 1 stage like FspSiliconInit. FSP specification >= 2.2
* has multiple stages as below.
*/
enum fsp_silicon_init_phases {
FSP_SILICON_INIT_API,
FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API,
FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API
};

static void fsps_return_value_handler(enum fsp_silicon_init_phases phases, uint32_t status)
{
uint8_t postcode;

/* Handle any reset request returned by FSP-S APIs */
fsp_handle_reset(status);

if (status == FSP_SUCCESS)
return;
/* Handle all other errors returned by FSP-S APIs */
/* Assume video failure if attempted to initialize graphics */
if (CONFIG(RUN_FSP_GOP) && vbt_get())
postcode = POST_VIDEO_FAILURE;
else
postcode = POST_HW_INIT_FAILURE; /* else generic */

switch (phases) {
case FSP_SILICON_INIT_API:
die_with_post_code(postcode, "FspSiliconInit returned with error 0x%08x\n",
status);
break;
case FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API:
printk(BIOS_SPEW, "FspMultiPhaseSiInit NumberOfPhases returned 0x%08x\n",
status);
break;
case FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API:
printk(BIOS_SPEW, "FspMultiPhaseSiInit ExecutePhase returned 0x%08x\n",
status);
break;
default:
break;
}
}

static void do_silicon_init(struct fsp_header *hdr)
{
FSPS_UPD *upd, *supd;
fsp_silicon_init_fn silicon_init;
uint32_t status;
uint8_t postcode;
const struct cbmem_entry *logo_entry = NULL;
fsp_multi_phase_si_init_fn multi_phase_si_init;
struct fsp_multi_phase_params multi_phase_params;
struct fsp_multi_phase_get_number_of_phases_params multi_phase_get_number;

supd = (FSPS_UPD *) (hdr->cfg_region_offset + hdr->image_base);

Expand Down Expand Up @@ -64,20 +125,49 @@ static void do_silicon_init(struct fsp_header *hdr)
cbmem_entry_remove(logo_entry);

fsp_debug_after_silicon_init(status);
fsps_return_value_handler(FSP_SILICON_INIT_API, status);

/* Handle any errors returned by FspSiliconInit */
fsp_handle_reset(status);
if (status != FSP_SUCCESS) {
/* Assume video failure if attempted to initialize graphics */
if (CONFIG(RUN_FSP_GOP) && vbt_get())
postcode = POST_VIDEO_FAILURE;
else
postcode = POST_HW_INIT_FAILURE; /* else generic */

printk(BIOS_SPEW, "FspSiliconInit returned 0x%08x\n", status);
die_with_post_code(postcode,
"FspSiliconInit returned an error!\n");
if (!CONFIG(PLATFORM_USES_FSP2_2))
return;

/* Check if SoC user would like to call Multi Phase Init */
if (!soc_fsp_multi_phase_init_is_enable())
return;

/* Call MultiPhaseSiInit */
multi_phase_si_init = (void *) (hdr->image_base +
hdr->multi_phase_si_init_entry_offset);

/* Implementing multi_phase_si_init() is optional as per FSP 2.2 spec */
if (multi_phase_si_init == NULL)
return;

post_code(POST_FSP_MULTI_PHASE_SI_INIT_ENTRY);
timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_START);
/* Get NumberOfPhases Value */
multi_phase_params.multi_phase_action = GET_NUMBER_OF_PHASES;
multi_phase_params.phase_index = 0;
multi_phase_params.multi_phase_param_ptr = &multi_phase_get_number;
status = multi_phase_si_init(&multi_phase_params);
fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API, status);

/* Execute Multi Phase Execution */
for (int i = 1; i <= multi_phase_get_number.number_of_phases; i++) {
printk(BIOS_SPEW, "Executing Phase %d of FspMultiPhaseSiInit\n", i);
/*
* Give SoC/mainboard a chance to perform any operation before
* Multi Phase Execution
*/
platform_fsp_multi_phase_init_cb(i);

multi_phase_params.multi_phase_action = EXECUTE_PHASE;
multi_phase_params.phase_index = i;
multi_phase_params.multi_phase_param_ptr = NULL;
status = multi_phase_si_init(&multi_phase_params);
fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API, status);
}
timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_END);
post_code(POST_FSP_MULTI_PHASE_SI_INIT_EXIT);
}

static int fsps_get_dest(const struct fsp_load_descriptor *fspld, void **dest,
Expand Down
2 changes: 2 additions & 0 deletions src/drivers/intel/fsp2_0/util.c
Expand Up @@ -49,6 +49,8 @@ enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob)
hdr->notify_phase_entry_offset = read32(raw_hdr + 56);
hdr->memory_init_entry_offset = read32(raw_hdr + 60);
hdr->silicon_init_entry_offset = read32(raw_hdr + 68);
if (CONFIG(PLATFORM_USES_FSP2_2))
hdr->multi_phase_si_init_entry_offset = read32(raw_hdr + 72);

return CB_SUCCESS;
}
Expand Down
9 changes: 0 additions & 9 deletions src/drivers/intel/gma/intel_ddi.c
@@ -1,16 +1,7 @@
/* SPDX-License-Identifier: MIT */

#include <types.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <console/console.h>
#include <acpi/acpi.h>
#include <device/pci.h>
#include <ec/google/chromeec/ec.h>
#include <cpu/x86/tsc.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/msr.h>
#include <edid.h>
#include <drivers/intel/gma/i915.h>

/* HDMI/DVI modes ignore everything but the last 2 items. So we share
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/ptt/ptt.c
Expand Up @@ -3,7 +3,6 @@
#include <soc/pci_devs.h>
#include <device/pci_ops.h>
#include <console/console.h>
#include <timer.h>

#include "ptt.h"

Expand Down
6 changes: 1 addition & 5 deletions src/drivers/intel/wifi/wifi.c
Expand Up @@ -73,10 +73,6 @@ static void wifi_pci_dev_init(struct device *dev)
}
}

static struct pci_operations pci_ops = {
.set_subsystem = pci_dev_set_subsystem,
};

struct device_operations device_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
Expand All @@ -85,7 +81,7 @@ struct device_operations device_ops = {
#if CONFIG(GENERATE_SMBIOS_TABLES)
.get_smbios_data = smbios_write_wifi,
#endif
.ops_pci = &pci_ops,
.ops_pci = &pci_dev_ops_pci,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_name = generic_wifi_acpi_name,
.acpi_fill_ssdt = intel_wifi_fill_ssdt,
Expand Down
279 changes: 153 additions & 126 deletions src/drivers/ipmi/ipmi_fru.c
Expand Up @@ -11,6 +11,7 @@
#define READ_FRU_DATA_RETRY_INTERVAL_MS 30 /* From IPMI spec v2.0 rev 1.1 */
#define OFFSET_LENGTH_MULTIPLIER 8 /* offsets/lengths are multiples of 8 */
#define NUM_DATA_BYTES(t) (t & 0x3f) /* Encoded in type/length byte */
#define FRU_END_OF_FIELDS 0xc1 /* type/length byte encoded to indicate no more info fields */

static enum cb_err ipmi_read_fru(const int port, struct ipmi_read_fru_data_req *req,
uint8_t *fru_data)
Expand Down Expand Up @@ -91,6 +92,127 @@ static uint8_t data2str(const uint8_t *frudata, char *stringdata, uint8_t length
return length;
}

/*
* Read data string from data_ptr and store it to string, return the
* length of the string or 0 when it's failed.
*/
static int read_data_string(const uint8_t *data_ptr, char **string)
{
uint8_t length;

length = NUM_DATA_BYTES(data_ptr[0]);
if (length == 0) {
printk(BIOS_DEBUG, "%s:%d - failed due to length is zero\n", __func__,
__LINE__);
return 0;
}

*string = malloc(length + 1);
if (!*string) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for string data.\n", __func__,
length + 1);
return 0;
}
if (!data2str((const uint8_t *)data_ptr, *string, length)) {
printk(BIOS_ERR, "%s:%d - data2str failed\n", __func__, __LINE__);
free(*string);
return 0;
}

return length;
}

static enum cb_err read_fru_chassis_info_area(const int port, const uint8_t id,
uint8_t offset, struct fru_chassis_info *info)
{
uint8_t length;
struct ipmi_read_fru_data_req req;
uint8_t *data_ptr, *end, *custom_data_ptr;
int ret = CB_SUCCESS;

if (!offset)
return CB_ERR;

offset = offset * OFFSET_LENGTH_MULTIPLIER;
req.fru_device_id = id;
/* Read Chassis Info Area length first. */
req.fru_offset = offset + 1;
req.count = sizeof(length);
if (ipmi_read_fru(port, &req, &length) != CB_SUCCESS || !length) {
printk(BIOS_ERR, "%s failed, length: %d\n", __func__, length);
return CB_ERR;
}
length = length * OFFSET_LENGTH_MULTIPLIER;
data_ptr = (uint8_t *)malloc(length);
if (!data_ptr) {
printk(BIOS_ERR, "malloc %d bytes for chassis info failed\n", length);
return CB_ERR;
}
end = data_ptr + length;
/* Read Chassis Info Area data. */
req.fru_offset = offset;
req.count = length;
if (ipmi_read_fru(port, &req, data_ptr) != CB_SUCCESS) {
printk(BIOS_ERR, "%s failed to read fru\n", __func__);
ret = CB_ERR;
goto out;
}
if (checksum(data_ptr, length)) {
printk(BIOS_ERR, "Bad FRU chassis info checksum.\n");
ret = CB_ERR;
goto out;
}
/* Read chassis type. */
info->chassis_type = data_ptr[CHASSIS_TYPE_OFFSET];

printk(BIOS_DEBUG, "Read chassis part number string.\n");
length = read_data_string(data_ptr + CHASSIS_TYPE_OFFSET + 1,
&info->chassis_partnumber);

printk(BIOS_DEBUG, "Read chassis serial number string.\n");
data_ptr += CHASSIS_TYPE_OFFSET + 1 + length + 1;
length = read_data_string(data_ptr, &info->serial_number);

printk(BIOS_DEBUG, "Read custom chassis info fields.\n");
data_ptr += length + 1;
/* Check how many valid custom fields first. */
info->custom_count = 0;
custom_data_ptr = data_ptr;
while ((data_ptr < end) && ((data_ptr[0] != FRU_END_OF_FIELDS))) {
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0)
info->custom_count++;
data_ptr += length + 1;
}
if (!info->custom_count)
goto out;

info->chassis_custom = malloc(info->custom_count * sizeof(char *));
if (!info->chassis_custom) {
printk(BIOS_ERR, "%s failed to malloc %ld bytes for "
"chassis custom data array.\n", __func__,
info->custom_count * sizeof(char *));
ret = CB_ERR;
goto out;
}

/* Start reading custom chassis data. */
data_ptr = custom_data_ptr;
int count = 0;
while ((data_ptr < end) && ((data_ptr[0] != FRU_END_OF_FIELDS))) {
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
length = read_data_string(data_ptr, info->chassis_custom + count);
count++;
}
data_ptr += length + 1;
}

out:
free(data_ptr);
return ret;
}

static void read_fru_board_info_area(const int port, const uint8_t id,
uint8_t offset, struct fru_board_info *info)
{
Expand Down Expand Up @@ -127,61 +249,21 @@ static void read_fru_board_info_area(const int port, const uint8_t id,
printk(BIOS_ERR, "Bad FRU board info checksum.\n");
goto out;
}
/* Read manufacturer string, bit[5:0] is the string length. */
length = NUM_DATA_BYTES(data_ptr[BOARD_MAN_TYPE_LEN_OFFSET]);
data_ptr += BOARD_MAN_TYPE_LEN_OFFSET;
if (length > 0) {
info->manufacturer = malloc(length + 1);
if (!info->manufacturer) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"manufacturer.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->manufacturer, length))
free(info->manufacturer);
}
printk(BIOS_DEBUG, "Read board manufacturer string\n");
length = read_data_string(data_ptr + BOARD_MAN_TYPE_LEN_OFFSET,
&info->manufacturer);

/* Read product name string. */
data_ptr += length + 1;
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
info->product_name = malloc(length+1);
if (!info->product_name) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"product_name.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->product_name, length))
free(info->product_name);
}
printk(BIOS_DEBUG, "Read board product name string.\n");
data_ptr += BOARD_MAN_TYPE_LEN_OFFSET + length + 1;
length = read_data_string(data_ptr, &info->product_name);

/* Read serial number string. */
printk(BIOS_DEBUG, "Read board serial number string.\n");
data_ptr += length + 1;
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
info->serial_number = malloc(length + 1);
if (!info->serial_number) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"serial_number.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->serial_number, length))
free(info->serial_number);
}
length = read_data_string(data_ptr, &info->serial_number);

/* Read part number string. */
printk(BIOS_DEBUG, "Read board part number string.\n");
data_ptr += length + 1;
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
info->part_number = malloc(length + 1);
if (!info->part_number) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"part_number.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->part_number, length))
free(info->part_number);
}
length = read_data_string(data_ptr, &info->part_number);

out:
free(data_ptr);
Expand Down Expand Up @@ -224,89 +306,29 @@ static void read_fru_product_info_area(const int port, const uint8_t id,
printk(BIOS_ERR, "Bad FRU product info checksum.\n");
goto out;
}
/* Read manufacturer string, bit[5:0] is the string length. */
length = NUM_DATA_BYTES(data_ptr[PRODUCT_MAN_TYPE_LEN_OFFSET]);
data_ptr += PRODUCT_MAN_TYPE_LEN_OFFSET;
if (length > 0) {
info->manufacturer = malloc(length + 1);
if (!info->manufacturer) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"manufacturer.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->manufacturer, length))
free(info->manufacturer);
}
printk(BIOS_DEBUG, "Read product manufacturer string.\n");
length = read_data_string(data_ptr + PRODUCT_MAN_TYPE_LEN_OFFSET,
&info->manufacturer);

/* Read product_name string. */
data_ptr += length + 1;
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
info->product_name = malloc(length + 1);
if (!info->product_name) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"product_name.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->product_name, length))
free(info->product_name);
}
data_ptr += PRODUCT_MAN_TYPE_LEN_OFFSET + length + 1;
printk(BIOS_DEBUG, "Read product_name string.\n");
length = read_data_string(data_ptr, &info->product_name);

/* Read product part/model number. */
data_ptr += length + 1;
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
info->product_partnumber = malloc(length + 1);
if (!info->product_partnumber) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"product_partnumber.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->product_partnumber, length))
free(info->product_partnumber);
}
printk(BIOS_DEBUG, "Read product part/model number.\n");
length = read_data_string(data_ptr, &info->product_partnumber);

/* Read product version string. */
data_ptr += length + 1;
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
info->product_version = malloc(length + 1);
if (!info->product_version) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"product_version.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->product_version, length))
free(info->product_version);
}
printk(BIOS_DEBUG, "Read product version string.\n");
length = read_data_string(data_ptr, &info->product_version);

/* Read serial number string. */
data_ptr += length + 1;
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
info->serial_number = malloc(length + 1);
if (!info->serial_number) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"serial_number.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->serial_number, length))
free(info->serial_number);
}
printk(BIOS_DEBUG, "Read serial number string.\n");
length = read_data_string(data_ptr, &info->serial_number);

/* Read asset tag string. */
data_ptr += length + 1;
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
info->asset_tag = malloc(length + 1);
if (!info->asset_tag) {
printk(BIOS_ERR, "%s failed to malloc %d bytes for "
"asset_tag.\n", __func__, length + 1);
goto out;
}
if (!data2str((const uint8_t *)data_ptr, info->asset_tag, length))
free(info->asset_tag);
}
printk(BIOS_DEBUG, "Read asset tag string.\n");
length = read_data_string(data_ptr, &info->asset_tag);

out:
free(data_ptr);
Expand Down Expand Up @@ -348,7 +370,8 @@ void read_fru_areas(const int port, const uint8_t id, uint16_t offset,
&fru_info_str->prod_info);
read_fru_board_info_area(port, id, fru_common_hdr.board_area_offset,
&fru_info_str->board_info);
/* ToDo: Add read_fru_chassis_info_area(). */
read_fru_chassis_info_area(port, id, fru_common_hdr.chassis_area_offset,
&fru_info_str->chassis_info);
}

void read_fru_one_area(const int port, const uint8_t id, uint16_t offset,
Expand Down Expand Up @@ -389,7 +412,11 @@ void read_fru_one_area(const int port, const uint8_t id, uint16_t offset,
read_fru_board_info_area(port, id, fru_common_hdr.board_area_offset,
&fru_info_str->board_info);
break;
/* ToDo: Add case for CHASSIS_INFO_AREA. */
case CHASSIS_INFO_AREA:
memset(&fru_info_str->chassis_info, 0, sizeof(fru_info_str->chassis_info));
read_fru_chassis_info_area(port, id, fru_common_hdr.chassis_area_offset,
&fru_info_str->chassis_info);
break;
default:
printk(BIOS_ERR, "Invalid fru_area: %d\n", fru_area);
break;
Expand Down
10 changes: 10 additions & 0 deletions src/drivers/ipmi/ipmi_ops.h
Expand Up @@ -88,6 +88,7 @@ struct ipmi_add_sel_rsp {
/* Platform Management FRU Information Storage Definition Spec. */
#define PRODUCT_MAN_TYPE_LEN_OFFSET 3
#define BOARD_MAN_TYPE_LEN_OFFSET 6
#define CHASSIS_TYPE_OFFSET 2

struct ipmi_fru_common_hdr {
uint8_t format_version;
Expand Down Expand Up @@ -117,9 +118,18 @@ struct fru_board_info {
char *part_number;
};

struct fru_chassis_info {
uint8_t chassis_type;
char *chassis_partnumber;
char *serial_number;
char **chassis_custom;
int custom_count; /* Number of custom fields */
};

struct fru_info_str {
struct fru_product_info prod_info;
struct fru_board_info board_info;
struct fru_chassis_info chassis_info;
};

enum typecode {
Expand Down
8 changes: 6 additions & 2 deletions src/drivers/mrc_cache/mrc_cache.c
Expand Up @@ -397,6 +397,7 @@ static void update_mrc_cache_by_type(int type)
return;

if (!mrc_cache_needs_update(&latest_rdev, to_be_updated)) {
printk(BIOS_DEBUG, "MRC: '%s' does not need update.\n", cr->name);
log_event_cache_update(cr->elog_slot, ALREADY_UPTODATE);
return;
}
Expand All @@ -405,10 +406,13 @@ static void update_mrc_cache_by_type(int type)

if (region_file_update_data(&cache_file,
cbmem_entry_start(to_be_updated),
cbmem_entry_size(to_be_updated)) < 0)
cbmem_entry_size(to_be_updated)) < 0) {
printk(BIOS_DEBUG, "MRC: failed to update '%s'.\n", cr->name);
log_event_cache_update(cr->elog_slot, UPDATE_FAILURE);
else
} else {
printk(BIOS_DEBUG, "MRC: updated '%s'.\n", cr->name);
log_event_cache_update(cr->elog_slot, UPDATE_SUCCESS);
}
}

/* Read flash status register to determine if write protect is active */
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/pc80/pc/Makefile.inc
Expand Up @@ -7,7 +7,7 @@ ramstage-$(CONFIG_SPKMODEM) += spkmodem.c
romstage-$(CONFIG_SPKMODEM) += spkmodem.c

bootblock-y += i8254.c
verstage-y += i8254.c
verstage_x86-y += i8254.c
romstage-y += i8254.c
ramstage-y += i8254.c
postcar-y += i8254.c
Expand Down
18 changes: 15 additions & 3 deletions src/drivers/pc80/rtc/Makefile.inc
@@ -1,17 +1,29 @@
ifeq ($(CONFIG_ARCH_X86),y)

all-$(CONFIG_DRIVERS_MC146818) += mc146818rtc_boot.c
bootblock-$(CONFIG_DRIVERS_MC146818) += mc146818rtc_boot.c
verstage-$(CONFIG_DRIVERS_MC146818) += mc146818rtc_boot.c
postcar-$(CONFIG_DRIVERS_MC146818) += mc146818rtc_boot.c
romstage-$(CONFIG_DRIVERS_MC146818) += mc146818rtc_boot.c
ramstage-$(CONFIG_DRIVERS_MC146818) += mc146818rtc_boot.c

bootblock-$(CONFIG_DRIVERS_MC146818) += mc146818rtc.c
postcar-$(CONFIG_DRIVERS_MC146818) += mc146818rtc.c
romstage-$(CONFIG_DRIVERS_MC146818) += mc146818rtc.c
ramstage-$(CONFIG_DRIVERS_MC146818) += mc146818rtc.c
smm-$(CONFIG_DRIVERS_MC146818) += mc146818rtc.c

all-$(CONFIG_USE_OPTION_TABLE) += option.c
bootblock-$(CONFIG_USE_OPTION_TABLE) += option.c
verstage-$(CONFIG_USE_OPTION_TABLE) += option.c
postcar-$(CONFIG_USE_OPTION_TABLE) += option.c
romstage-$(CONFIG_USE_OPTION_TABLE) += option.c
ramstage-$(CONFIG_USE_OPTION_TABLE) += option.c
smm-$(CONFIG_USE_OPTION_TABLE) += option.c

all-$(CONFIG_CMOS_POST) += post.c
bootblock-$(CONFIG_CMOS_POST) += post.c
verstage-$(CONFIG_CMOS_POST) += post.c
postcar-$(CONFIG_CMOS_POST) += post.c
romstage-$(CONFIG_CMOS_POST) += post.c
ramstage-$(CONFIG_CMOS_POST) += post.c

ifeq ($(CONFIG_USE_OPTION_TABLE),y)
cbfs-files-$(CONFIG_HAVE_CMOS_DEFAULT) += cmos.default
Expand Down
1 change: 0 additions & 1 deletion src/drivers/pc80/rtc/mc146818rtc.c
Expand Up @@ -9,7 +9,6 @@
#include <option.h>
#include <pc80/mc146818rtc.h>
#include <rtc.h>
#include <cbfs.h>
#include <security/vboot/vbnv.h>
#include <security/vboot/vbnv_layout.h>
#include <types.h>
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/pc80/tpm/tis.c
Expand Up @@ -395,7 +395,7 @@ static u32 tis_probe(void)

didvid = tpm_read_did_vid(0);
if (!didvid || (didvid == 0xffffffff)) {
printf("%s: No TPM device found\n", __FUNCTION__);
printf("%s: No TPM device found\n", __func__);
return TPM_DRIVER_ERR;
}

Expand Down
12 changes: 10 additions & 2 deletions src/drivers/smmstore/smi.c
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <commonlib/region.h>
#include <cpu/x86/smm.h>
#include <smmstore.h>
#include <stddef.h>
#include <stdint.h>
Expand All @@ -10,13 +12,14 @@
*
* Legal means:
* - not pointing into SMRAM
* - ...?
*
* returns 0 on success, -1 on failure
*/
static int range_check(void *start, size_t size)
{
// TODO: fill in
if (smm_points_to_smram(start, size))
return -1;

return 0;
}

Expand All @@ -30,6 +33,9 @@ uint32_t smmstore_exec(uint8_t command, void *param)
printk(BIOS_DEBUG, "Reading from SMM store\n");
struct smmstore_params_read *params = param;

if (range_check(params, sizeof(*params)) != 0)
break;

if (range_check(params->buf, params->bufsize) != 0)
break;

Expand All @@ -42,6 +48,8 @@ uint32_t smmstore_exec(uint8_t command, void *param)
printk(BIOS_DEBUG, "Appending into SMM store\n");
struct smmstore_params_append *params = param;

if (range_check(params, sizeof(*params)) != 0)
break;
if (range_check(params->key, params->keysize) != 0)
break;
if (range_check(params->val, params->valsize) != 0)
Expand Down
12 changes: 10 additions & 2 deletions src/drivers/spi/boot_device_rw_nommap.c
Expand Up @@ -96,9 +96,17 @@ int boot_device_wp_region(const struct region_device *rd,
if (type == MEDIA_WP) {
if (spi_flash_is_write_protected(boot_dev,
region_device_region(rd)) != 1) {
enum spi_flash_status_reg_lockdown lock =
SPI_WRITE_PROTECTION_REBOOT;
if (CONFIG(BOOTMEDIA_SPI_LOCK_REBOOT))
lock = SPI_WRITE_PROTECTION_REBOOT;
else if (CONFIG(BOOTMEDIA_SPI_LOCK_PIN))
lock = SPI_WRITE_PROTECTION_PIN;
else if (CONFIG(BOOTMEDIA_SPI_LOCK_PERMANENT))
lock = SPI_WRITE_PROTECTION_PERMANENT;

return spi_flash_set_write_protected(boot_dev,
region_device_region(rd), true,
SPI_WRITE_PROTECTION_REBOOT);
region_device_region(rd), lock);
}

/* Already write protected */
Expand Down
4 changes: 1 addition & 3 deletions src/drivers/spi/spi_flash.c
Expand Up @@ -4,7 +4,6 @@
#include <boot_device.h>
#include <boot/coreboot_tables.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <string.h>
#include <spi-generic.h>
#include <spi_flash.h>
Expand Down Expand Up @@ -562,7 +561,6 @@ int spi_flash_is_write_protected(const struct spi_flash *flash,

int spi_flash_set_write_protected(const struct spi_flash *flash,
const struct region *region,
const bool non_volatile,
const enum spi_flash_status_reg_lockdown mode)
{
struct region flash_region = { 0 };
Expand All @@ -582,7 +580,7 @@ int spi_flash_set_write_protected(const struct spi_flash *flash,
return -1;
}

ret = flash->prot_ops->set_write(flash, region, non_volatile, mode);
ret = flash->prot_ops->set_write(flash, region, mode);

if (ret == 0 && mode != SPI_WRITE_PROTECTION_PRESERVE) {
printk(BIOS_INFO, "SPI: SREG lock-down was set to ");
Expand Down
77 changes: 33 additions & 44 deletions src/drivers/spi/winbond.c
Expand Up @@ -10,7 +10,7 @@
#include "spi_flash_internal.h"
#include "spi_winbond.h"

union status_reg1_bp3 {
union status_reg1 {
uint8_t u;
struct {
uint8_t busy : 1;
Expand All @@ -19,18 +19,14 @@ union status_reg1_bp3 {
uint8_t tb : 1;
uint8_t sec : 1;
uint8_t srp0 : 1;
};
};

union status_reg1_bp4 {
uint8_t u;
} bp3;
struct {
uint8_t busy : 1;
uint8_t wel : 1;
uint8_t bp : 4;
uint8_t tb : 1;
uint8_t srp0 : 1;
};
} bp4;
};

union status_reg2 {
Expand All @@ -50,15 +46,9 @@ struct status_regs {
struct {
#if defined(__BIG_ENDIAN)
union status_reg2 reg2;
union {
union status_reg1_bp3 reg1_bp3;
union status_reg1_bp4 reg1_bp4;
};
union status_reg1 reg1;
#else
union {
union status_reg1_bp3 reg1_bp3;
union status_reg1_bp4 reg1_bp4;
};
union status_reg1 reg1;
union status_reg2 reg2;
#endif
};
Expand Down Expand Up @@ -327,33 +317,28 @@ static int winbond_get_write_protection(const struct spi_flash *flash,

const size_t granularity = (1 << params->protection_granularity_shift);

if (params->bp_bits == 3) {
union status_reg1_bp3 reg1_bp3 = { .u = 0 };
union status_reg1 reg1 = { .u = 0 };

ret = spi_flash_cmd(&flash->spi, flash->status_cmd, &reg1_bp3.u,
sizeof(reg1_bp3.u));
ret = spi_flash_cmd(&flash->spi, flash->status_cmd, &reg1.u,
sizeof(reg1.u));
if (ret)
return ret;

if (reg1_bp3.sec) {
if (params->bp_bits == 3) {
if (reg1.bp3.sec) {
// FIXME: not supported
return -1;
}

bp = reg1_bp3.bp;
tb = reg1_bp3.tb;
bp = reg1.bp3.bp;
tb = reg1.bp3.tb;
} else if (params->bp_bits == 4) {
union status_reg1_bp4 reg1_bp4 = { .u = 0 };

ret = spi_flash_cmd(&flash->spi, flash->status_cmd, &reg1_bp4.u,
sizeof(reg1_bp4.u));

bp = reg1_bp4.bp;
tb = reg1_bp4.tb;
bp = reg1.bp4.bp;
tb = reg1.bp4.tb;
} else {
// FIXME: not supported
return -1;
}
if (ret)
return ret;

ret = spi_flash_cmd(&flash->spi, CMD_W25_RDSR2, &reg2.u,
sizeof(reg2.u));
Expand Down Expand Up @@ -482,15 +467,13 @@ static int winbond_flash_cmd_status(const struct spi_flash *flash,
*
* @param flash: The flash to operate on
* @param region: The region to write protect
* @param non_volatile: Make setting permanent
* @param mode: Optional status register lock-down mode
*
* @return 0 on success
*/
static int
winbond_set_write_protection(const struct spi_flash *flash,
const struct region *region,
const bool non_volatile,
const enum spi_flash_status_reg_lockdown mode)
{
const struct spi_flash_part_id *params;
Expand Down Expand Up @@ -544,13 +527,19 @@ winbond_set_write_protection(const struct spi_flash *flash,
/* Write block protection bits */

if (params->bp_bits == 3) {
val.reg1_bp3 = (union status_reg1_bp3) { .bp = bp, .tb = tb,
.sec = 0 };
mask.reg1_bp3 = (union status_reg1_bp3) { .bp = ~0, .tb = 1,
.sec = 1 };
val.reg1 = (union status_reg1) {
.bp3 = { .bp = bp, .tb = tb, .sec = 0 }
};
mask.reg1 = (union status_reg1) {
.bp3 = { .bp = ~0, .tb = 1, .sec = 1 }
};
} else {
val.reg1_bp4 = (union status_reg1_bp4) { .bp = bp, .tb = tb };
mask.reg1_bp4 = (union status_reg1_bp4) { .bp = ~0, .tb = 1 };
val.reg1 = (union status_reg1) {
.bp4 = { .bp = bp, .tb = tb }
};
mask.reg1 = (union status_reg1) {
.bp4 = { .bp = ~0, .tb = 1 }
};
}

val.reg2 = (union status_reg2) { .cmp = cmp };
Expand All @@ -576,18 +565,18 @@ winbond_set_write_protection(const struct spi_flash *flash,
}

if (params->bp_bits == 3) {
val.reg1_bp3.srp0 = !!(srp & 1);
mask.reg1_bp3.srp0 = 1;
val.reg1.bp3.srp0 = !!(srp & 1);
mask.reg1.bp3.srp0 = 1;
} else {
val.reg1_bp4.srp0 = !!(srp & 1);
mask.reg1_bp4.srp0 = 1;
val.reg1.bp4.srp0 = !!(srp & 1);
mask.reg1.bp4.srp0 = 1;
}

val.reg2.srp1 = !!(srp & 2);
mask.reg2.srp1 = 1;
}

ret = winbond_flash_cmd_status(flash, mask.u, val.u, non_volatile);
ret = winbond_flash_cmd_status(flash, mask.u, val.u, true);
if (ret)
return ret;

Expand Down
12 changes: 1 addition & 11 deletions src/drivers/tpm/tpm.c
@@ -1,24 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi.h>
#include <types.h>
#include <stddef.h>
#include <bootstate.h>
#include <security/tpm/tspi.h>

#if CONFIG(HAVE_ACPI_RESUME)
#include <acpi/acpi.h>
#endif

static void init_tpm_dev(void *unused)
{
#if CONFIG(HAVE_ACPI_RESUME)
int s3resume = acpi_is_wakeup_s3();
tpm_setup(s3resume);
#else
/* This can lead to PCR reset attacks but currently there
is no generic way to detect resume on other platforms. */
tpm_setup(false);
#endif
}

BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, init_tpm_dev, NULL);
2 changes: 2 additions & 0 deletions src/drivers/uart/acpi/Kconfig
@@ -0,0 +1,2 @@
config DRIVERS_UART_ACPI
bool
1 change: 1 addition & 0 deletions src/drivers/uart/acpi/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_UART_ACPI) += acpi.c