9 changes: 3 additions & 6 deletions src/arch/x86/acpi_s3.c
Expand Up @@ -57,11 +57,6 @@ extern unsigned int __wakeup_size;

static void acpi_jump_to_wakeup(void *vector)
{
if (!acpi_s3_resume_allowed()) {
printk(BIOS_WARNING, "ACPI: S3 resume not allowed.\n");
return;
}

/* Copy wakeup trampoline in place. */
memcpy((void *)WAKEUP_BASE, &__wakeup, __wakeup_size);

Expand All @@ -76,7 +71,7 @@ void __weak mainboard_suspend_resume(void)
{
}

void acpi_resume(void *wake_vec)
void __noreturn acpi_resume(void *wake_vec)
{
/* Restore GNVS pointer in SMM if found. */
apm_control(APM_CNT_GNVS_UPDATE);
Expand All @@ -86,4 +81,6 @@ void acpi_resume(void *wake_vec)

post_code(POST_OS_RESUME);
acpi_jump_to_wakeup(wake_vec);

die("Failed the jump to wakeup vector\n");
}
14 changes: 14 additions & 0 deletions src/arch/x86/assembly_entry.S
Expand Up @@ -15,12 +15,22 @@
#define _STACK_TOP _ecar_stack
#endif

#ifdef __x86_64__
.code64
#else
.code32
#endif

.section ".text._start", "ax", @progbits
.global _start
_start:

/* Migrate GDT to this text segment */
#ifdef __x86_64__
call gdt_init64
#else
call gdt_init
#endif

/* reset stack pointer to CAR/EARLYRAM stack */
mov $_STACK_TOP, %esp
Expand Down Expand Up @@ -49,6 +59,10 @@ debug_spinloop:
#if CONFIG(IDT_IN_EVERY_STAGE)
call exception_init
#endif

#if CONFIG(ASAN_IN_ROMSTAGE)
call asan_init
#endif
call car_stage_entry

/* Expect to never return. */
Expand Down
10 changes: 10 additions & 0 deletions src/arch/x86/boot.c
@@ -1,10 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <arch/boot/boot.h>
#include <commonlib/helpers.h>
#include <console/console.h>
#include <program_loading.h>
#include <ip_checksum.h>
#include <symbols.h>
#include <assert.h>

int payload_arch_usable_ram_quirk(uint64_t start, uint64_t size)
{
Expand All @@ -19,6 +21,13 @@ int payload_arch_usable_ram_quirk(uint64_t start, uint64_t size)

void arch_prog_run(struct prog *prog)
{
#if ENV_RAMSTAGE && defined(__x86_64__)
const uint32_t arg = pointer_to_uint32_safe(prog_entry_arg(prog));
const uint32_t entry = pointer_to_uint32_safe(prog_entry(prog));

/* On x86 coreboot payloads expect to be called in protected mode */
protected_mode_jump(entry, arg);
#else
#ifdef __x86_64__
void (*doit)(void *arg);
#else
Expand All @@ -27,4 +36,5 @@ void arch_prog_run(struct prog *prog)
#endif
doit = prog_entry(prog);
doit(prog_entry_arg(prog));
#endif
}
38 changes: 38 additions & 0 deletions src/arch/x86/c_exit.S
@@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <arch/ram_segs.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/cr.h>


#ifdef __x86_64__

/*
* Functions to handle mode switches from long mode to protected
* mode.
*/
.text
.code64
.section ".text.protected_mode_jump", "ax", @progbits
.globl protected_mode_jump
protected_mode_jump:

push %rbp
mov %rsp, %rbp

/* Arguments to stack */
push %rdi
push %rsi

#include <cpu/x86/64bit/exit32.inc>

movl -8(%ebp), %eax /* Function to call */
movl -16(%ebp), %ebx /* Argument 0 */

/* Align the stack */
andl $0xFFFFFFF0, %esp
subl $12, %esp
pushl %ebx /* Argument 0 */

jmp *%eax
#endif
4 changes: 4 additions & 0 deletions src/arch/x86/c_start.S
Expand Up @@ -91,6 +91,10 @@ _start:

andl $0xFFFFFFF0, %esp

#if CONFIG(ASAN_IN_RAMSTAGE)
call asan_init
#endif

#if CONFIG(GDB_WAIT)
call gdb_hw_init
call gdb_stub_breakpoint
Expand Down
6 changes: 5 additions & 1 deletion src/arch/x86/car.ld
Expand Up @@ -72,8 +72,12 @@
*(.sbss.*)
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
_ebss = .;
_car_unallocated_start = .;

#if ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE)
_shadow_size = (_ebss - _car_region_start) >> 3;
REGION(asan_shadow, ., _shadow_size, ARCH_POINTER_ALIGN_SIZE)
#endif
_car_unallocated_start = .;
_car_region_end = . + CONFIG_DCACHE_RAM_SIZE - (. - _car_region_start);
}
. = _car_region_end;
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/cpu.c
Expand Up @@ -287,7 +287,6 @@ void cpu_initialize(unsigned int index)
printk(BIOS_DEBUG, "Using generic CPU ops (good)\n");
}


/* Initialize the CPU */
if (cpu->ops && cpu->ops->init) {
cpu->enabled = 1;
Expand Down
5 changes: 0 additions & 5 deletions src/arch/x86/exception.c
Expand Up @@ -180,8 +180,6 @@ static uint32_t gdb_stub_registers[NUM_REGS];
#define GDB_EXC_SOFTWARE 149 /* Software generated exception */
#define GDB_EXC_BREAKPOINT 150 /* Breakpoint */



static unsigned char exception_to_signal[] = {
[0] = GDB_SIGFPE, /* divide by zero */
[1] = GDB_SIGTRAP, /* debug exception */
Expand Down Expand Up @@ -222,7 +220,6 @@ static const char hexchars[] = "0123456789abcdef";
static char in_buffer[BUFMAX];
static char out_buffer[BUFMAX];


static inline void stub_putc(int ch)
{
gdb_tx_byte(ch);
Expand Down Expand Up @@ -283,7 +280,6 @@ static void copy_to_hex(char *buf, void *addr, unsigned long count)
*buf = 0;
}


/* convert the hex array pointed to by buf into binary to be placed in mem */
/* return a pointer to the character AFTER the last byte written */
static void copy_from_hex(void *addr, char *buf, unsigned long count)
Expand All @@ -298,7 +294,6 @@ static void copy_from_hex(void *addr, char *buf, unsigned long count)
}
}


/* scan for the sequence $<data>#<checksum> */

static int get_packet(char *buffer)
Expand Down
63 changes: 53 additions & 10 deletions src/arch/x86/exit_car.S
Expand Up @@ -2,6 +2,7 @@

#include <cpu/x86/mtrr.h>
#include <cpu/x86/cr.h>
#include <cpu/x86/cache.h>

.section ".module_parameters", "aw", @progbits
/* stack_top indicates the stack to pull MTRR information from. */
Expand All @@ -10,14 +11,42 @@ post_car_stack_top:
.long 0
.long 0

#if defined(__x86_64__)
.code64
.macro pop_eax_edx
pop %rax
mov %rax, %rdx
shr $32, %rdx
.endm
.macro pop_ebx_esi
pop %rbx
mov %rbx, %rsi
shr $32, %rsi
.endm
#else
.code32
.macro pop_eax_edx
pop %eax
pop %edx
.endm
.macro pop_ebx_esi
pop %ebx
pop %esi
.endm
#endif

.text
.global _start
_start:
/* Assume stack alignment doesn't matter here as chipset_teardown_car
is expected to be implemented in assembly. */

/* Migrate GDT to this text segment */
#if defined(__x86_64__)
call gdt_init64
#else
call gdt_init
#endif

#ifdef __x86_64__
mov %rdi, _cbmem_top_ptr
Expand All @@ -26,15 +55,27 @@ _start:
movl 4(%esp), %eax
movl %eax, _cbmem_top_ptr
#endif

/* Make sure _cbmem_top_ptr hits dram before invd */
movl $1, %eax
cpuid
btl $CPUID_FEATURE_CLFLUSH_BIT, %edx
jz skip_clflush
clflush _cbmem_top_ptr

skip_clflush:
/* chipset_teardown_car() is expected to disable cache-as-ram. */
call chipset_teardown_car

/* Enable caching if not already enabled. */
#ifdef __x86_64__
mov %cr0, %rax
and $(~(CR0_CD | CR0_NW)), %eax
mov %rax, %cr0
#else
mov %cr0, %eax
and $(~(CR0_CD | CR0_NW)), %eax
mov %eax, %cr0

#endif
/* Ensure cache is clean. */
invd

Expand All @@ -61,8 +102,13 @@ _start:
/* Need to align stack to 16 bytes at the call instruction. Therefore
account for the 1 push. */
andl $0xfffffff0, %esp
#if defined(__x86_64__)
mov %rbp, %rdi
#else
sub $12, %esp
push %ebp
#endif

call soc_set_mtrrs
/* Ignore fixing up %esp since we're setting it a new value. */

Expand All @@ -73,7 +119,7 @@ _start:
call soc_enable_mtrrs
#else /* CONFIG_SOC_SETS_MSRS */
/* Clear variable MTRRs. */
pop %ebx /* Number to clear */
pop_ebx_esi /* ebx: Number to clear, esi: Number to set */
test %ebx, %ebx
jz 2f
xor %eax, %eax
Expand All @@ -89,23 +135,20 @@ _start:
2:

/* Set Variable MTRRs based on stack contents. */
pop %ebx /* Number to set. */
test %ebx, %ebx
test %esi, %esi
jz 2f
mov $(MTRR_PHYS_BASE(0)), %ecx
1:
/* Write MTRR base. */
pop %eax
pop %edx
pop_eax_edx
wrmsr
inc %ecx
/* Write MTRR mask. */
pop %eax
pop %edx
pop_eax_edx
wrmsr
inc %ecx

dec %ebx
dec %esi
jnz 1b
2:

Expand Down
29 changes: 29 additions & 0 deletions src/arch/x86/gdt_init.S
Expand Up @@ -15,6 +15,35 @@ gdtptr:
.word gdt_end - gdt -1 /* compute the table limit */
.long gdt /* we know the offset */

#ifdef __x86_64__
.code64
.section ".text._gdt64_", "ax", @progbits
.globl gdt_init64
gdt_init64:
/* Workaround a bug in the assembler.
* The following code doesn't work:
* lgdt gdtptr64
*
* The assembler tries to save memory by using 32bit displacement addressing mode.
* Displacements are using signed integers.
* This is fine in protected mode, as the negative address points to the correct
* address > 2GiB, but in long mode this doesn't work at all.
* Tests showed that QEMU can gracefully handle it, but real CPUs can't.
*
* Use the movabs pseudo instruction to force using a 64bit absolute address.
*/
movabs $gdtptr64, %rax
lgdt (%rax)
ret

.previous
.align 4
.globl gdtptr64
gdtptr64:
.word gdt_end - gdt -1 /* compute the table limit */
.quad gdt /* we know the offset */
#endif

.align 4
gdt:
/* selgdt 0, unused */
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/include/arch/bert_storage.h
Expand Up @@ -82,7 +82,6 @@ static inline acpi_hest_generic_data_v300_t *acpi_hest_generic_data3(
/* Find the address of a Generic Data structure's CPER error record section */
#define section_of_acpientry(A, B) ((typeof(A))((u8 *)(B) + sizeof(*(B))))


/* Add a context to an existing IA32/X64-type error entry */
cper_ia32x64_context_t *new_cper_ia32x64_ctx(
acpi_generic_error_status_t *status,
Expand Down
11 changes: 11 additions & 0 deletions src/arch/x86/include/arch/boot/boot.h
Expand Up @@ -7,4 +7,15 @@
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_386

#include <types.h>
/*
* Jump to function in protected mode.
* @arg func_ptr Function to jump to in protected mode
* @arg Argument to pass to called function
*
* @noreturn
*/
void protected_mode_jump(uint32_t func_ptr,
uint32_t argument);

#endif /* ASM_I386_BOOT_H */
6 changes: 6 additions & 0 deletions src/arch/x86/include/arch/cpu.h
Expand Up @@ -269,6 +269,12 @@ static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)

}

/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
static __always_inline void cpu_relax(void)
{
__asm__ __volatile__("rep;nop" : : : "memory");
}

#define asmlinkage __attribute__((regparm(0)))

/*
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/include/arch/io.h
Expand Up @@ -73,7 +73,6 @@ static inline void outsl(uint16_t port, const void *addr, unsigned long count)
);
}


static inline void insb(uint16_t port, void *addr, unsigned long count)
{
__asm__ __volatile__ (
Expand Down
2 changes: 0 additions & 2 deletions src/arch/x86/include/arch/smp/atomic.h
Expand Up @@ -67,6 +67,4 @@ static __always_inline void atomic_dec(atomic_t *v)
: "m" (v->counter));
}



#endif /* ARCH_SMP_ATOMIC_H */
2 changes: 0 additions & 2 deletions src/arch/x86/include/arch/smp/mpspec.h
Expand Up @@ -23,7 +23,6 @@
*/
#define MAX_APICS 16


#define SMP_FLOATING_TABLE_LEN sizeof(struct intel_mp_floating)

struct intel_mp_floating {
Expand Down Expand Up @@ -130,7 +129,6 @@ enum mp_irq_source_types {
#define MP_IRQ_TRIGGER_LEVEL 0xc
#define MP_IRQ_TRIGGER_MASK 0xc


struct mpc_config_lintsrc {
u8 mpc_type;
u8 mpc_irqtype;
Expand Down
9 changes: 1 addition & 8 deletions src/arch/x86/include/arch/smp/spinlock.h
Expand Up @@ -29,6 +29,7 @@ typedef struct {
#define barrier() __asm__ __volatile__("" : : : "memory")
#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0)
#define spin_unlock_wait(x) do { barrier(); } while (spin_is_locked(x))
#undef barrier

#define spin_lock_string \
"\n1:\t" \
Expand Down Expand Up @@ -62,21 +63,13 @@ static __always_inline void spin_unlock(spinlock_t *lock)
: "=m" (lock->lock) : : "memory");
}

/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
static __always_inline void cpu_relax(void)
{
__asm__ __volatile__("rep;nop" : : : "memory");
}

#else

#define DECLARE_SPIN_LOCK(x)
#define barrier() do {} while (0)
#define spin_is_locked(lock) 0
#define spin_unlock_wait(lock) do {} while (0)
#define spin_lock(lock) do {} while (0)
#define spin_unlock(lock) do {} while (0)
#define cpu_relax() do {} while (0)

#endif

Expand Down
8 changes: 8 additions & 0 deletions src/arch/x86/memcpy.c
@@ -1,11 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <string.h>
#include <stdbool.h>
#include <asan.h>

void *memcpy(void *dest, const void *src, size_t n)
{
unsigned long d0, d1, d2;

#if (ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE)) || \
(ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE))
check_memory_region((unsigned long)src, n, false, _RET_IP_);
check_memory_region((unsigned long)dest, n, true, _RET_IP_);
#endif

asm volatile(
#ifdef __x86_64__
"rep ; movsd\n\t"
Expand Down
8 changes: 8 additions & 0 deletions src/arch/x86/memmove.c
Expand Up @@ -4,12 +4,20 @@
*/

#include <string.h>
#include <stdbool.h>
#include <asan.h>

void *memmove(void *dest, const void *src, size_t n)
{
int d0, d1, d2, d3, d4, d5;
char *ret = dest;

#if (ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE)) || \
(ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE))
check_memory_region((unsigned long)src, n, false, _RET_IP_);
check_memory_region((unsigned long)dest, n, true, _RET_IP_);
#endif

__asm__ __volatile__(
/* Handle more 16bytes in loop */
"cmp $0x10, %0\n\t"
Expand Down
7 changes: 7 additions & 0 deletions src/arch/x86/memset.c
Expand Up @@ -4,6 +4,8 @@

#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <asan.h>

typedef uint32_t op_t;

Expand All @@ -12,6 +14,11 @@ void *memset(void *dstpp, int c, size_t len)
int d0;
unsigned long int dstp = (unsigned long int) dstpp;

#if (ENV_ROMSTAGE && CONFIG(ASAN_IN_ROMSTAGE)) || \
(ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE))
check_memory_region((unsigned long)dstpp, len, true, _RET_IP_);
#endif

/* This explicit register allocation improves code very much indeed. */
register op_t x asm("ax");

Expand Down
3 changes: 0 additions & 3 deletions src/arch/x86/pirq_routing.c
Expand Up @@ -28,7 +28,6 @@ static void check_pirq_routing_table(struct irq_routing_table *rt)
printk(BIOS_DEBUG, "%s(): Interrupt Routing Table located at %p.\n",
__func__, addr);


sum = rt->checksum - sum;

if (sum != rt->checksum) {
Expand Down Expand Up @@ -106,8 +105,6 @@ static u8 pirq_get_next_free_irq(u8 *pirq, u16 bitmap)
/* If it's not yet routed, use it */
if (!already_routed)
break;
/* But if it was already routed, try the next one */
continue;
}
/* Now we got our IRQ */
return irq;
Expand Down
504 changes: 247 additions & 257 deletions src/arch/x86/smbios.c

Large diffs are not rendered by default.

139 changes: 139 additions & 0 deletions src/arch/x86/smbios_defaults.c
@@ -0,0 +1,139 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <memory_info.h>
#include <smbios.h>
#include <stdint.h>
#include <string.h>

/* this function will fill the corresponding locator */
__weak void smbios_fill_dimm_locator(const struct dimm_info *dimm, struct smbios_type17 *t)
{
char locator[40];

snprintf(locator, sizeof(locator), "Channel-%d-DIMM-%d",
dimm->channel_num, dimm->dimm_num);
t->device_locator = smbios_add_string(t->eos, locator);

snprintf(locator, sizeof(locator), "BANK %d", dimm->bank_locator);
t->bank_locator = smbios_add_string(t->eos, locator);
}

__weak const char *smbios_mainboard_bios_version(void)
{
return NULL;
}

__weak const char *smbios_mainboard_serial_number(void)
{
return CONFIG_MAINBOARD_SERIAL_NUMBER;
}

__weak const char *smbios_mainboard_version(void)
{
return CONFIG_MAINBOARD_VERSION;
}

__weak const char *smbios_mainboard_manufacturer(void)
{
return CONFIG_MAINBOARD_SMBIOS_MANUFACTURER;
}

__weak const char *smbios_mainboard_product_name(void)
{
return CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME;
}

__weak const char *smbios_mainboard_asset_tag(void)
{
return "";
}

__weak u8 smbios_mainboard_feature_flags(void)
{
return 0;
}

__weak const char *smbios_mainboard_location_in_chassis(void)
{
return "";
}

__weak smbios_board_type smbios_mainboard_board_type(void)
{
return SMBIOS_BOARD_TYPE_UNKNOWN;
}

/*
* System Enclosure or Chassis Types as defined in SMBIOS specification.
* The default value is SMBIOS_ENCLOSURE_DESKTOP (0x03) but laptop,
* convertible, or tablet enclosure will be used if the appropriate
* system type is selected.
*/
__weak smbios_enclosure_type smbios_mainboard_enclosure_type(void)
{
if (CONFIG(SYSTEM_TYPE_LAPTOP))
return SMBIOS_ENCLOSURE_LAPTOP;
else if (CONFIG(SYSTEM_TYPE_TABLET))
return SMBIOS_ENCLOSURE_TABLET;
else if (CONFIG(SYSTEM_TYPE_CONVERTIBLE))
return SMBIOS_ENCLOSURE_CONVERTIBLE;
else if (CONFIG(SYSTEM_TYPE_DETACHABLE))
return SMBIOS_ENCLOSURE_DETACHABLE;
else
return SMBIOS_ENCLOSURE_DESKTOP;
}

__weak const char *smbios_system_serial_number(void)
{
return smbios_mainboard_serial_number();
}

__weak const char *smbios_system_version(void)
{
return smbios_mainboard_version();
}

__weak const char *smbios_system_manufacturer(void)
{
return smbios_mainboard_manufacturer();
}

__weak const char *smbios_system_product_name(void)
{
return smbios_mainboard_product_name();
}

__weak void smbios_system_set_uuid(u8 *uuid)
{
/* leave all zero */
}

__weak unsigned int smbios_cpu_get_max_speed_mhz(void)
{
return 0; /* Unknown */
}

__weak unsigned int smbios_cpu_get_current_speed_mhz(void)
{
return 0; /* Unknown */
}

__weak const char *smbios_system_sku(void)
{
return "";
}

__weak const char *smbios_chassis_version(void)
{
return "";
}

__weak const char *smbios_chassis_serial_number(void)
{
return "";
}

__weak const char *smbios_processor_serial_number(void)
{
return "";
}
1 change: 1 addition & 0 deletions src/arch/x86/walkcbfs.S
Expand Up @@ -20,6 +20,7 @@

#define CBFS_FILE_STRUCTSIZE (CBFS_FILE_OFFSET + 4)

.code32
.section .text
.global walkcbfs_asm

Expand Down
1 change: 0 additions & 1 deletion src/console/printk.c
Expand Up @@ -10,7 +10,6 @@
#include <console/vtxprintf.h>
#include <smp/spinlock.h>
#include <smp/node.h>
#include <stddef.h>
#include <trace.h>
#include <timer.h>

Expand Down
1 change: 0 additions & 1 deletion src/cpu/Makefile.inc
@@ -1,7 +1,6 @@
################################################################################
## Subdirectories
################################################################################
subdirs-y += allwinner
subdirs-y += amd
subdirs-y += armltd
subdirs-y += intel
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/car/romstage.c
Expand Up @@ -2,7 +2,6 @@

#include <arch/cpu.h>
#include <arch/romstage.h>
#include <bootblock_common.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <arch/symbols.h>
Expand Down
7 changes: 6 additions & 1 deletion src/cpu/intel/common/common.h
Expand Up @@ -3,7 +3,7 @@
#ifndef _CPU_INTEL_COMMON_H
#define _CPU_INTEL_COMMON_H

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

void set_vmx_and_lock(void);
void set_feature_ctrl_vmx(void);
Expand All @@ -17,6 +17,11 @@ void set_feature_ctrl_lock(void);
struct cppc_config;
void cpu_init_cppc_config(struct cppc_config *config, u32 version);

/*
* Returns true if CPU supports Hyper-Threading.
*/
bool intel_ht_supported(void);

/*
* Returns true if it's not thread 0 on a hyperthreading enabled core.
*/
Expand Down
6 changes: 3 additions & 3 deletions src/cpu/intel/common/common_init.c
Expand Up @@ -103,15 +103,15 @@ void cpu_init_cppc_config(struct cppc_config *config, u32 version)
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = 8,
.bit_offset = 0,
.access_size = 4,
.access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS,
.addrl = 0,
.addrh = 0,
};
static const acpi_addr_t unsupported = {
.space_id = ACPI_ADDRESS_SPACE_MEMORY,
.bit_width = 0,
.bit_offset = 0,
.access_size = 0,
.access_size = ACPI_ACCESS_SIZE_UNDEFINED,
.addrl = 0,
.addrh = 0,
};
Expand Down Expand Up @@ -259,7 +259,7 @@ void cpu_init_cppc_config(struct cppc_config *config, u32 version)
msr.space_id = ACPI_ADDRESS_SPACE_MEMORY;
msr.bit_width = 32;
msr.bit_offset = 0;
msr.access_size = 0;
msr.access_size = ACPI_ACCESS_SIZE_UNDEFINED;
msr.addrl = 1;
config->regs[CPPC_AUTO_SELECT] = msr;
}
Expand Down
1 change: 1 addition & 0 deletions src/cpu/intel/common/fsb.c
Expand Up @@ -45,6 +45,7 @@ static int get_fsb_tsc(int *fsb, int *ratio)
case 0x3a: /* IvyBridge BCLK fixed at 100MHz */
case 0x3c: /* Haswell BCLK fixed at 100MHz */
case 0x45: /* Haswell-ULT BCLK fixed at 100MHz */
case 0x46: /* Haswell-GT3e BCLK fixed at 100MHz */
*fsb = 100;
*ratio = (rdmsr(MSR_PLATFORM_INFO).lo >> 8) & 0xff;
break;
Expand Down
10 changes: 8 additions & 2 deletions src/cpu/intel/common/hyperthreading.c
Expand Up @@ -3,6 +3,13 @@
#include <cpu/x86/lapic.h>
#include <cpu/intel/common/common.h>
#include <arch/cpu.h>
#include <types.h>

bool intel_ht_supported(void)
{
/* Is HyperThreading supported? */
return !!(cpuid_edx(1) & CPUID_FEAURE_HTT);
}

/*
* Return true if running thread does not have the smallest lapic ID
Expand All @@ -13,8 +20,7 @@ bool intel_ht_sibling(void)
struct cpuid_result result;
unsigned int core_ids, apic_ids, threads;

/* Is Hyper-Threading supported */
if (!(cpuid_edx(1) & CPUID_FEAURE_HTT))
if (!intel_ht_supported())
return false;

apic_ids = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/haswell/Kconfig
Expand Up @@ -10,7 +10,6 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select MMX
select SSE2
select UDELAY_TSC
Expand All @@ -22,6 +21,7 @@ config CPU_SPECIFIC_OPTIONS
select PARALLEL_MP
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select HAVE_ASAN_IN_ROMSTAGE

config SMM_TSEG_SIZE
hex
Expand Down
2 changes: 2 additions & 0 deletions src/cpu/intel/haswell/haswell_init.c
Expand Up @@ -778,6 +778,8 @@ static const struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, 0x306c3 }, /* Intel Haswell C0 */
{ X86_VENDOR_INTEL, 0x40650 }, /* Intel Haswell ULT B0 */
{ X86_VENDOR_INTEL, 0x40651 }, /* Intel Haswell ULT B1 */
{ X86_VENDOR_INTEL, 0x40660 }, /* Intel Crystal Well C0 */
{ X86_VENDOR_INTEL, 0x40661 }, /* Intel Crystal Well C1 */
{ 0, 0 },
};

Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_1067x/Kconfig
Expand Up @@ -4,7 +4,6 @@ config CPU_INTEL_MODEL_1067X
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SSE2
select UDELAY_TSC
select TSC_MONOTONIC_TIMER
Expand Down
4 changes: 2 additions & 2 deletions src/cpu/intel/model_1067x/model_1067x_init.c
Expand Up @@ -9,7 +9,7 @@
#include <cpu/x86/cache.h>
#include <cpu/x86/name.h>
#include <cpu/intel/smm_reloc.h>
#include <cpu/intel/common/common.h>

#include "chip.h"

static void init_timer(void)
Expand Down Expand Up @@ -292,7 +292,7 @@ static struct device_operations cpu_dev_ops = {
};

static const struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, 0x10676 }, /* Intel Core 2 Solo/Core Duo */
{ X86_VENDOR_INTEL, 0x10676 },
{ X86_VENDOR_INTEL, 0x10677 },
{ X86_VENDOR_INTEL, 0x1067A },
{ 0, 0 },
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_1067x/mp_init.c
Expand Up @@ -63,7 +63,7 @@ static void per_cpu_smm_trigger(void)
} else {
if (!CONFIG(SET_IA32_FC_LOCK_BIT))
printk(BIOS_INFO,
"Overriding CONFIG_SET_IA32_FC_LOCK_BIT to enable SMRR\n");
"Overriding CONFIG(SET_IA32_FC_LOCK_BIT) to enable SMRR\n");
ia32_ft_ctrl.lo |= (1 << 3) | (1 << 0);
wrmsr(IA32_FEATURE_CONTROL, ia32_ft_ctrl);
}
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_106cx/Kconfig
Expand Up @@ -4,7 +4,6 @@ config CPU_INTEL_MODEL_106CX
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SSE2
select UDELAY_TSC
select TSC_MONOTONIC_TIMER
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_106cx/model_106cx_init.c
Expand Up @@ -8,7 +8,6 @@
#include <cpu/intel/speedstep.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/name.h>
#include <cpu/intel/common/common.h>

#define HIGHEST_CLEVEL 3
static void configure_c_states(void)
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_2065x/Kconfig
Expand Up @@ -9,7 +9,6 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SSE2
select UDELAY_TSC
select TSC_MONOTONIC_TIMER
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_206ax/Kconfig
Expand Up @@ -9,7 +9,6 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select MMX
select SSE2
select UDELAY_TSC
Expand Down
3 changes: 2 additions & 1 deletion src/cpu/intel/model_206ax/acpi.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <types.h>
#include <console/console.h>
#include <acpi/acpi.h>
#include <acpi/acpigen.h>
Expand All @@ -9,6 +8,8 @@
#include <cpu/intel/speedstep.h>
#include <cpu/intel/turbo.h>
#include <device/device.h>
#include <stdint.h>

#include "model_206ax.h"
#include "chip.h"

Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_206ax/finalize.c
Expand Up @@ -2,7 +2,6 @@

#include <arch/cpu.h>
#include <cpu/x86/msr.h>
#include <cpu/intel/speedstep.h>
#include "model_206ax.h"

/* MSR Documentation based on
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_6ex/Kconfig
Expand Up @@ -4,7 +4,6 @@ config CPU_INTEL_MODEL_6EX
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SSE2
select UDELAY_TSC
select TSC_MONOTONIC_TIMER
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_6ex/model_6ex_init.c
Expand Up @@ -8,7 +8,6 @@
#include <cpu/intel/speedstep.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/name.h>
#include <cpu/intel/common/common.h>

#define HIGHEST_CLEVEL 3
static void configure_c_states(void)
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_6fx/Kconfig
Expand Up @@ -4,7 +4,6 @@ config CPU_INTEL_MODEL_6FX
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SSE2
select UDELAY_TSC
select TSC_MONOTONIC_TIMER
Expand Down
3 changes: 2 additions & 1 deletion src/cpu/intel/model_6fx/Makefile.inc
Expand Up @@ -4,4 +4,5 @@ subdirs-y += ../common
ramstage-$(CONFIG_PARALLEL_MP) += ../model_1067x/mp_init.c
subdirs-y += ../smm/gen1

cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-0f-*)
cpu_microcode_bins += $(wildcard 3rdparty/intel-microcode/intel-ucode/06-0f-*) \
3rdparty/intel-microcode/intel-ucode/06-16-01
2 changes: 0 additions & 2 deletions src/cpu/intel/model_6fx/model_6fx_init.c
Expand Up @@ -8,7 +8,6 @@
#include <cpu/intel/speedstep.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/name.h>
#include <cpu/intel/common/common.h>

#define HIGHEST_CLEVEL 3
static void configure_c_states(void)
Expand Down Expand Up @@ -147,7 +146,6 @@ static const struct cpu_device_id cpu_table[] = {
{ X86_VENDOR_INTEL, 0x06fb }, /* Intel Core 2 Solo/Core Duo */
{ X86_VENDOR_INTEL, 0x06fd }, /* Intel Core 2 Solo/Core Duo */
{ X86_VENDOR_INTEL, 0x10661 }, /* Intel Core 2 Celeron Conroe-L */
{ X86_VENDOR_INTEL, 0x10676 }, /* Core2 Duo E8200 */
{ 0, 0 },
};

Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_f2x/Kconfig
Expand Up @@ -4,7 +4,6 @@ config CPU_INTEL_MODEL_F2X
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SUPPORT_CPU_UCODE_IN_CBFS
select SMM_ASEG
select CPU_INTEL_COMMON
Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/model_f3x/Kconfig
Expand Up @@ -4,7 +4,6 @@ config CPU_INTEL_MODEL_F3X
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SUPPORT_CPU_UCODE_IN_CBFS
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_HYPERTHREADING
1 change: 0 additions & 1 deletion src/cpu/intel/model_f4x/Kconfig
Expand Up @@ -4,5 +4,4 @@ config CPU_INTEL_MODEL_F4X
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SUPPORT_CPU_UCODE_IN_CBFS
25 changes: 21 additions & 4 deletions src/cpu/qemu-x86/Kconfig
Expand Up @@ -2,12 +2,29 @@

config CPU_QEMU_X86
bool
select ARCH_BOOTBLOCK_X86_32
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select UDELAY_TSC
select TSC_MONOTONIC_TIMER
select UNKNOWN_TSC_RATE
select SMM_ASEG

if CPU_QEMU_X86

config CPU_QEMU_X86_64
bool "Experimental 64bit support"
select ARCH_BOOTBLOCK_X86_64
select ARCH_VERSTAGE_X86_64
select ARCH_ROMSTAGE_X86_64
select ARCH_POSTCAR_X86_64
select ARCH_RAMSTAGE_X86_64

config CPU_QEMU_X86_32
bool
default n if CPU_QEMU_X86_64
default y
select ARCH_BOOTBLOCK_X86_32
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_POSTCAR_X86_32
select ARCH_RAMSTAGE_X86_32
endif
5 changes: 3 additions & 2 deletions src/cpu/qemu-x86/cache_as_ram_bootblock.S
Expand Up @@ -29,11 +29,12 @@ cache_as_ram:

/* Restore the BIST result and timestamps. */
#if defined(__x86_64__)
movd %mm1, %rdi
movd %mm2, %rdi
shld %rdi, 32
movd %mm1, %rsi
or %rsi, %rdi
movd %mm2, %rsi

movd %mm0, %rsi
#else
sub $4, %esp

Expand Down
1 change: 0 additions & 1 deletion src/cpu/ti/Kconfig

This file was deleted.

1 change: 0 additions & 1 deletion src/cpu/ti/Makefile.inc

This file was deleted.

12 changes: 10 additions & 2 deletions src/cpu/x86/64bit/exit32.inc
Expand Up @@ -12,14 +12,22 @@

#include <cpu/x86/msr.h>
#include <cpu/x86/cr.h>
#if defined(__RAMSTAGE__)
#include <arch/ram_segs.h>
#define CODE_SEG RAM_CODE_SEG
#define DATA_SEG RAM_DATA_SEG
#else
#include <arch/rom_segs.h>
#define CODE_SEG ROM_CODE_SEG
#define DATA_SEG ROM_DATA_SEG
#endif

drop_longmode:
/* Ensure cache is clean. */
wbinvd

/* Set 32-bit code segment and ss */
mov $ROM_CODE_SEG, %rcx
mov $CODE_SEG, %rcx
/* SetCodeSelector32 will drop us to protected mode on return */
call SetCodeSelector32

Expand Down Expand Up @@ -54,7 +62,7 @@ __longmode_compatibility:
/* Running in 32-bit compatibility mode */

/* Use flat data segment */
movl $ROM_DATA_SEG, %eax
movl $DATA_SEG, %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %ss
Expand Down
8 changes: 8 additions & 0 deletions src/cpu/x86/Kconfig
Expand Up @@ -121,6 +121,14 @@ config SMM_STUB_STACK_SIZE

endif

config X86_SMM_LOADER_VERSION2
bool
default n
depends on HAVE_SMI_HANDLER
help
This option enables SMM module loader that works with server
platforms which may contain more than 32 CPU threads.

config SMM_LAPIC_REMAP_MITIGATION
bool
default y if NORTHBRIDGE_INTEL_I945
Expand Down
39 changes: 31 additions & 8 deletions src/cpu/x86/mp_init.c
Expand Up @@ -726,12 +726,21 @@ static void asmlinkage smm_do_relocation(void *arg)
* the location of the new SMBASE. If using SMM modules then this
* calculation needs to match that of the module loader.
*/
#if CONFIG(X86_SMM_LOADER_VERSION2)
perm_smbase = smm_get_cpu_smbase(cpu);
mp_state.perm_smbase = perm_smbase;
if (!perm_smbase) {
printk(BIOS_ERR, "%s: bad SMBASE for CPU %d\n", __func__, cpu);
return;
}
#else
perm_smbase = mp_state.perm_smbase;
perm_smbase -= cpu * runtime->save_state_size;

printk(BIOS_DEBUG, "New SMBASE 0x%08lx\n", perm_smbase);
#endif

/* Setup code checks this callback for validity. */
printk(BIOS_INFO, "%s : curr_smbase 0x%x perm_smbase 0x%x, cpu = %d\n",
__func__, (int)curr_smbase, (int)perm_smbase, cpu);
mp_state.ops.relocation_handler(cpu, curr_smbase, perm_smbase);

if (CONFIG(STM)) {
Expand All @@ -758,9 +767,17 @@ static void adjust_smm_apic_id_map(struct smm_loader_params *smm_params)

static int install_relocation_handler(int num_cpus, size_t save_state_size)
{
int cpus = num_cpus;
#if CONFIG(X86_SMM_LOADER_VERSION2)
/* Default SMRAM size is not big enough to concurrently
* handle relocation for more than ~32 CPU threads
* therefore, relocate 1 by 1. */
cpus = 1;
#endif

struct smm_loader_params smm_params = {
.per_cpu_stack_size = CONFIG_SMM_STUB_STACK_SIZE,
.num_concurrent_stacks = num_cpus,
.num_concurrent_stacks = cpus,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = 1,
.handler = smm_do_relocation,
Expand All @@ -770,9 +787,10 @@ static int install_relocation_handler(int num_cpus, size_t save_state_size)
if (mp_state.ops.adjust_smm_params != NULL)
mp_state.ops.adjust_smm_params(&smm_params, 0);

if (smm_setup_relocation_handler(&smm_params))
if (smm_setup_relocation_handler(&smm_params)) {
printk(BIOS_ERR, "%s: smm setup failed\n", __func__);
return -1;

}
adjust_smm_apic_id_map(&smm_params);

return 0;
Expand All @@ -781,8 +799,13 @@ static int install_relocation_handler(int num_cpus, size_t save_state_size)
static int install_permanent_handler(int num_cpus, uintptr_t smbase,
size_t smsize, size_t save_state_size)
{
/* There are num_cpus concurrent stacks and num_cpus concurrent save
* state areas. Lastly, set the stack size to 1KiB. */
/*
* All the CPUs will relocate to permanaent handler now. Set parameters
* needed for all CPUs. The placement of each CPUs entry point is
* determined by the loader. This code simply provides the beginning of
* SMRAM region, the number of CPUs who will use the handler, the stack
* size and save state size for each CPU.
*/
struct smm_loader_params smm_params = {
.per_cpu_stack_size = CONFIG_SMM_MODULE_STACK_SIZE,
.num_concurrent_stacks = num_cpus,
Expand All @@ -794,7 +817,7 @@ static int install_permanent_handler(int num_cpus, uintptr_t smbase,
if (mp_state.ops.adjust_smm_params != NULL)
mp_state.ops.adjust_smm_params(&smm_params, 1);

printk(BIOS_DEBUG, "Installing SMM handler to 0x%08lx\n", smbase);
printk(BIOS_DEBUG, "Installing permanent SMM handler to 0x%08lx\n", smbase);

if (smm_load_module((void *)smbase, smsize, &smm_params))
return -1;
Expand Down
4 changes: 4 additions & 0 deletions src/cpu/x86/smm/Makefile.inc
@@ -1,6 +1,10 @@
## SPDX-License-Identifier: GPL-2.0-only

ifeq ($(CONFIG_X86_SMM_LOADER_VERSION2),y)
ramstage-y += smm_module_loaderv2.c
else
ramstage-y += smm_module_loader.c
endif
ramstage-y += smi_trigger.c

ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/smm/smm_module_handler.c
Expand Up @@ -99,7 +99,7 @@ void *smm_get_save_state(int cpu)

/* This function assumes all save states start at top of default
* SMRAM size space and are staggered down by save state size. */
base = (void *)smm_runtime->smbase;
base = (void *)(uintptr_t)smm_runtime->smbase;
base += SMM_DEFAULT_SIZE;
base -= (cpu + 1) * smm_runtime->save_state_size;

Expand Down
655 changes: 655 additions & 0 deletions src/cpu/x86/smm/smm_module_loaderv2.c

Large diffs are not rendered by default.

52 changes: 48 additions & 4 deletions src/cpu/x86/smm/smm_stub.S
Expand Up @@ -10,6 +10,7 @@
*/

#include <cpu/x86/cr.h>
#include <cpu/x86/msr.h>

.code32
.section ".module_parameters", "aw", @progbits
Expand Down Expand Up @@ -148,8 +149,8 @@ smm_trampoline32:
pushl $0x0
mov %esp, %ebp

/* Allocate locals (fxsave) */
subl $0x4, %esp
/* Allocate locals (fxsave, efer_backup) */
subl $0xc, %esp

/* calculate fxsave location */
mov fxsave_area, %edi
Expand Down Expand Up @@ -177,22 +178,65 @@ smm_trampoline32:
/* Align stack to 16 bytes. Another 32 bytes are pushed below. */
andl $0xfffffff0, %esp

#ifdef __x86_64__
mov %ecx, %edi
/* Backup IA32_EFER. Preserves ebx. */
movl $(IA32_EFER), %ecx
rdmsr
movl %eax, -0x8(%ebp)
movl %edx, -0xc(%ebp)

/* entry64.inc preserves ebx, esi, edi */
#include <cpu/x86/64bit/entry64.inc>
mov %edi, %ecx

#endif

/* Call into the c-based SMM relocation function with the platform
* parameters. Equivalent to:
* struct arg = { c_handler_params, cpu_num, smm_runtime, canary };
* c_handler(&arg)
*/
#ifdef __x86_64__
push %rbx /* uintptr_t *canary */
push $(smm_runtime)
push %rcx /* size_t cpu */
push c_handler_arg /* void *arg */

mov %rsp, %rdi /* *arg */

movl c_handler, %eax
call *%rax

/*
* The only reason to go back to protected mode is that RSM doesn't restore
* MSR registers and MSR IA32_EFER was modified by entering long mode.
* Drop to protected mode to safely operate on the IA32_EFER MSR.
*/

/* Disable long mode. */
#include <cpu/x86/64bit/exit32.inc>

/* Restore IA32_EFER as RSM doesn't restore MSRs. */
movl $(IA32_EFER), %ecx
rdmsr
movl -0x8(%ebp), %eax
movl -0xc(%ebp), %edx

wrmsr

#else
push $0x0 /* Padding */
push $0x0 /* Padding */
push $0x0 /* Padding */
push %ebx /* uintptr_t *canary */
push $(smm_runtime)
push %ecx /* int cpu */
push %ecx /* size_t cpu */
push c_handler_arg /* void *arg */
push %esp /* smm_module_params *arg (allocated on stack). */
mov c_handler, %eax
call *%eax

#endif
/* Retrieve fxsave location. */
mov -4(%ebp), %edi
test %edi, %edi
Expand Down
3 changes: 1 addition & 2 deletions src/cpu/x86/tsc/delay_tsc.c
@@ -1,8 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <arch/cpu.h>
#include <cpu/x86/tsc.h>
#include <pc80/i8254.h>
#include <smp/spinlock.h>
#include <delay.h>
#include <thread.h>

Expand Down
86 changes: 40 additions & 46 deletions src/device/azalia_device.c
Expand Up @@ -7,10 +7,6 @@
#include <device/mmio.h>
#include <delay.h>

#define HDA_ICII_REG 0x68
#define HDA_ICII_BUSY (1 << 0)
#define HDA_ICII_VALID (1 << 1)

static int set_bits(void *port, u32 mask, u32 val)
{
u32 reg32;
Expand All @@ -23,9 +19,7 @@ static int set_bits(void *port, u32 mask, u32 val)
reg32 |= val;
write32(port, reg32);

/* Wait for readback of register to
* match what was just written to it
*/
/* Wait for readback of register to match what was just written to it */
count = 50;
do {
/* Wait 1ms based on BKDG wait time */
Expand All @@ -46,13 +40,13 @@ static int codec_detect(u8 *base)
int count;

/* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
if (set_bits(base + 0x08, 1, 1) == -1)
if (set_bits(base + HDA_GCTL_REG, 1, HDA_GCTL_CRST) == -1)
goto no_codec;

/* clear STATESTS bits (BAR + 0xE)[2:0] */
reg32 = read32(base + 0x0E);
/* clear STATESTS bits (BAR + 0xe)[2:0] */
reg32 = read32(base + HDA_STATESTS_REG);
reg32 |= 7;
write32(base + 0x0E, reg32);
write32(base + HDA_STATESTS_REG, reg32);

/* Wait for readback of register to
* match what was just written to it
Expand All @@ -61,22 +55,22 @@ static int codec_detect(u8 *base)
do {
/* Wait 1ms based on BKDG wait time */
mdelay(1);
reg32 = read32(base + 0x0E);
reg32 = read32(base + HDA_STATESTS_REG);
} while ((reg32 != 0) && --count);
/* Timeout occurred */
if (!count)
goto no_codec;

/* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */
if (set_bits(base + 0x08, 1, 0) == -1)
/* Set Bit 0 to 0 to enter reset state (BAR + 0x8)[0] */
if (set_bits(base + HDA_GCTL_REG, 1, 0) == -1)
goto no_codec;

/* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
if (set_bits(base + 0x08, 1, 1) == -1)
if (set_bits(base + HDA_GCTL_REG, 1, HDA_GCTL_CRST) == -1)
goto no_codec;

/* Read in Codec location (BAR + 0xe)[2..0] */
reg32 = read32(base + 0xe);
reg32 = read32(base + HDA_STATESTS_REG);
reg32 &= 0x0f;
if (!reg32)
goto no_codec;
Expand All @@ -86,7 +80,7 @@ static int codec_detect(u8 *base)
no_codec:
/* Codec Not found */
/* Put HDA back in reset (BAR + 0x8) [0] */
set_bits(base + 0x08, 1, 0);
set_bits(base + HDA_GCTL_REG, 1, 0);
printk(BIOS_DEBUG, "azalia_audio: No codec!\n");
return 0;
}
Expand All @@ -112,16 +106,14 @@ static u32 find_verb(struct device *dev, u32 viddid, const u32 **verb)
return 0;
}

/**
* Wait 50usec for the codec to indicate it is ready
* no response would imply that the codec is non-operative
/*
* Wait 50usec for the codec to indicate it is ready.
* No response would imply that the codec is non-operative.
*/

static int wait_for_ready(u8 *base)
{
/* Use a 50 usec timeout - the Linux kernel uses the
* same duration */

/* Use a 50 usec timeout - the Linux kernel uses the same duration */
int timeout = 50;

while (timeout--) {
Expand All @@ -134,29 +126,29 @@ static int wait_for_ready(u8 *base)
return -1;
}

/**
* Wait 50usec for the codec to indicate that it accepted
* the previous command. No response would imply that the code
* is non-operative
/*
* Wait 50usec for the codec to indicate that it accepted the previous command.
* No response would imply that the code is non-operative.
*/

static int wait_for_valid(u8 *base)
{
/* Use a 50 usec timeout - the Linux kernel uses the
* same duration */

u32 reg32;
/* Use a 50 usec timeout - the Linux kernel uses the same duration */
int timeout = 25;

write32(base + HDA_ICII_REG,
HDA_ICII_VALID | HDA_ICII_BUSY);
/* Send the verb to the codec */
reg32 = read32(base + HDA_ICII_REG);
reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
write32(base + HDA_ICII_REG, reg32);

while (timeout--) {
udelay(1);
}
timeout = 50;
while (timeout--) {
u32 reg32 = read32(base + HDA_ICII_REG);
if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) ==
HDA_ICII_VALID)
reg32 = read32(base + HDA_ICII_REG);
if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == HDA_ICII_VALID)
return 0;
udelay(1);
}
Expand All @@ -174,18 +166,21 @@ static void codec_init(struct device *dev, u8 *base, int addr)
printk(BIOS_DEBUG, "azalia_audio: Initializing codec #%d\n", addr);

/* 1 */
if (wait_for_ready(base) == -1)
if (wait_for_ready(base) == -1) {
printk(BIOS_DEBUG, " codec not ready.\n");
return;
}

reg32 = (addr << 28) | 0x000f0000;
write32(base + 0x60, reg32);
write32(base + HDA_IC_REG, reg32);

if (wait_for_valid(base) == -1)
if (wait_for_valid(base) == -1) {
printk(BIOS_DEBUG, " codec not valid.\n");
return;

reg32 = read32(base + 0x64);
}

/* 2 */
reg32 = read32(base + HDA_IR_REG);
printk(BIOS_DEBUG, "azalia_audio: codec viddid: %08x\n", reg32);
verb_size = find_verb(dev, reg32, &verb);

Expand All @@ -200,7 +195,7 @@ static void codec_init(struct device *dev, u8 *base, int addr)
if (wait_for_ready(base) == -1)
return;

write32(base + 0x60, verb[i]);
write32(base + HDA_IC_REG, verb[i]);

if (wait_for_valid(base) == -1)
return;
Expand All @@ -224,19 +219,18 @@ void azalia_audio_init(struct device *dev)
struct resource *res;
u32 codec_mask;

res = find_resource(dev, 0x10);
res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!res)
return;

// NOTE this will break as soon as the azalia_audio get's a bar above
// 4G. Is there anything we can do about it?
// NOTE this will break as soon as the azalia_audio get's a bar above 4G.
// Is there anything we can do about it?
base = res2mmio(res, 0, 0);
printk(BIOS_DEBUG, "azalia_audio: base = %p\n", base);
codec_mask = codec_detect(base);

if (codec_mask) {
printk(BIOS_DEBUG, "azalia_audio: codec_mask = %02x\n",
codec_mask);
printk(BIOS_DEBUG, "azalia_audio: codec_mask = %02x\n", codec_mask);
codecs_init(dev, base, codec_mask);
}
}
Expand Down
1 change: 0 additions & 1 deletion src/device/cardbus_device.c
Expand Up @@ -119,7 +119,6 @@ void cardbus_enable_resources(struct device *dev)

ctrl = pci_read_config16(dev, PCI_CB_BRIDGE_CONTROL);
ctrl |= (dev->link_list->bridge_ctrl & (
PCI_BRIDGE_CTL_NO_ISA |
PCI_BRIDGE_CTL_VGA |
PCI_BRIDGE_CTL_MASTER_ABORT |
PCI_BRIDGE_CTL_BUS_RESET));
Expand Down
31 changes: 29 additions & 2 deletions src/device/device_const.c
Expand Up @@ -184,7 +184,7 @@ DEVTREE_CONST struct device *find_dev_path(
DEVTREE_CONST struct device *child;

if (!parent) {
assert(0);
BUG();
/* Return NULL in case asserts are considered non-fatal. */
return NULL;
}
Expand All @@ -196,6 +196,33 @@ DEVTREE_CONST struct device *find_dev_path(
return child;
}

/**
* Find the device structure given an array of nested device paths,
*
* @param parent The parent bus to start the search on.
* @param nested_path An array of relative paths from the parent bus to the target device.
* @param nested_path_length Number of path elements in nested_path array.
* @return Pointer to a device structure for the device at nested path
* or 0/NULL if no device is found.
*/
DEVTREE_CONST struct device *find_dev_nested_path(
const struct bus *parent, const struct device_path nested_path[],
size_t nested_path_length)
{
DEVTREE_CONST struct device *child;

if (!parent || !nested_path || !nested_path_length)
return NULL;

child = find_dev_path(parent, nested_path);

/* Terminate recursion at end of nested path or child not found */
if (nested_path_length == 1 || !child)
return child;

return find_dev_nested_path(child->link_list, nested_path + 1, nested_path_length - 1);
}

DEVTREE_CONST struct device *pcidev_path_behind(
const struct bus *parent, pci_devfn_t devfn)
{
Expand Down Expand Up @@ -255,7 +282,7 @@ DEVTREE_CONST struct device *pcidev_path_behind_pci2pci_bridge(
pci_devfn_t devfn)
{
if (!bridge || (bridge->path.type != DEVICE_PATH_PCI)) {
assert(0);
BUG();
/* Return NULL in case asserts are non-fatal. */
return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion src/device/dram/ddr2.c
Expand Up @@ -653,7 +653,7 @@ static void print_us(const char *msg, u32 val)
/**
* \brief Print the info in DIMM
*
* Print info about the DIMM. Useful to use when CONFIG_DEBUG_RAM_SETUP is
* Print info about the DIMM. Useful to use when CONFIG(DEBUG_RAM_SETUP) is
* selected, or for a purely informative output.
*
* @param dimm pointer to already decoded @ref dimm_attr structure
Expand Down
2 changes: 1 addition & 1 deletion src/device/dram/ddr3.c
Expand Up @@ -593,7 +593,7 @@ static void print_ns(const char *msg, u32 val)
/**
* \brief Print the info in DIMM
*
* Print info about the DIMM. Useful to use when CONFIG_DEBUG_RAM_SETUP is
* Print info about the DIMM. Useful to use when CONFIG(DEBUG_RAM_SETUP) is
* selected, or for a purely informative output.
*
* @param dimm pointer to already decoded @ref dimm_attr structure
Expand Down
2 changes: 1 addition & 1 deletion src/device/oprom/realmode/x86.c
Expand Up @@ -130,7 +130,7 @@ static void setup_interrupt_handlers(void)
{
/* If the mainboard_interrupt_handler isn't called first.
*/
if(!intXX_handler[i])
if (!intXX_handler[i])
{
/* Now set the default functions that are actually
* needed to initialize the option roms. This is
Expand Down
2 changes: 1 addition & 1 deletion src/device/oprom/x86emu/debug.c
Expand Up @@ -170,7 +170,7 @@ void x86emu_decode_printf (const char *x)
void x86emu_decode_printf2 (const char *x, int y)
{
char temp[100];
snprintf(temp, sizeof (temp), x,y);
snprintf(temp, sizeof(temp), x,y);
strcpy(M.x86.decoded_buf+M.x86.enc_str_pos,temp);
M.x86.enc_str_pos += strlen(temp);
}
Expand Down
4 changes: 2 additions & 2 deletions src/device/pci_rom.c
Expand Up @@ -264,8 +264,8 @@ void pci_rom_ssdt(const struct device *device)
{
static size_t ngfx;

/* Only handle VGA devices */
if ((device->class >> 8) != PCI_CLASS_DISPLAY_VGA)
/* Only handle display devices */
if ((device->class >> 16) != PCI_BASE_CLASS_DISPLAY)
return;

/* Only handle enabled devices */
Expand Down
1 change: 0 additions & 1 deletion src/drivers/amd/agesa/bootblock.c
Expand Up @@ -2,7 +2,6 @@

#include <bootblock_common.h>
#include <halt.h>
#include <timestamp.h>
#include <amdblocks/amd_pci_mmconf.h>
#include <amdblocks/biosram.h>
#include <arch/bootblock.h>
Expand Down
1 change: 0 additions & 1 deletion src/drivers/amd/agesa/state_machine.c
Expand Up @@ -5,7 +5,6 @@
#include <acpi/acpi.h>
#include <bootstate.h>
#include <cbfs.h>
#include <cbmem.h>
#include <timestamp.h>

#include <northbridge/amd/agesa/state_machine.h>
Expand Down
5 changes: 5 additions & 0 deletions src/drivers/amd/i2s_machine_dev/i2s_machine_dev.c
Expand Up @@ -21,6 +21,11 @@ static void i2s_machine_dev_fill_ssdt(const struct device *dev)

dmic_select_gpio = &cfg->dmic_select_gpio;

if (scope == NULL) {
printk(BIOS_ERR, "%s: ERROR: ACPI I2S scope not found\n", dev_path(dev));
return;
}

if (cfg->hid == NULL) {
printk(BIOS_ERR, "%s: ERROR: HID required\n", dev_path(dev));
return;
Expand Down
5 changes: 3 additions & 2 deletions src/drivers/aspeed/common/ast_main.c
Expand Up @@ -4,6 +4,7 @@
*/

#include <delay.h>
#include <device/pci_def.h>

#include "ast_drv.h"
#include "ast_dram_tables.h"
Expand Down Expand Up @@ -329,7 +330,7 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
ast->dev = dev;

/* PCI BAR 1 */
res = find_resource(dev->pdev, 0x14);
res = find_resource(dev->pdev, PCI_BASE_ADDRESS_1);
if (!res) {
dev_err(dev->pdev, "BAR1 resource not found.\n");
ret = -EIO;
Expand All @@ -343,7 +344,7 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)

/* PCI BAR 2 */
ast->io_space_uses_mmap = false;
res = find_resource(dev->pdev, 0x18);
res = find_resource(dev->pdev, PCI_BASE_ADDRESS_2);
if (!res) {
dev_err(dev->pdev, "BAR2 resource not found.\n");
ret = -EIO;
Expand Down
3 changes: 2 additions & 1 deletion src/drivers/aspeed/common/ast_mode_corebootfb.c
Expand Up @@ -3,6 +3,7 @@
* Copied from Linux drivers/gpu/drm/ast/ast_mode.c
*/
#include <edid.h>
#include <device/pci_def.h>

#include "ast_drv.h"

Expand All @@ -18,7 +19,7 @@ int ast_crtc_do_set_base(struct drm_crtc *crtc)
struct drm_framebuffer *fb = crtc->primary->fb;

/* PCI BAR 0 */
struct resource *res = find_resource(crtc->dev->pdev, 0x10);
struct resource *res = find_resource(crtc->dev->pdev, PCI_BASE_ADDRESS_0);
if (!res) {
printk(BIOS_ERR, "BAR0 resource not found.\n");
return -EIO;
Expand Down
1 change: 0 additions & 1 deletion src/drivers/crb/tpm.c
Expand Up @@ -14,7 +14,6 @@

#include <timer.h>
#include <console/console.h>
#include <delay.h>
#include <device/mmio.h>
#include <string.h>
#include <soc/pci_devs.h>
Expand Down
2 changes: 2 additions & 0 deletions src/drivers/genesyslogic/gl9763e/Kconfig
@@ -0,0 +1,2 @@
config DRIVERS_GENESYSLOGIC_GL9763E
bool
1 change: 1 addition & 0 deletions src/drivers/genesyslogic/gl9763e/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_GENESYSLOGIC_GL9763E) += gl9763e.c
53 changes: 53 additions & 0 deletions src/drivers/genesyslogic/gl9763e/gl9763e.c
@@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0-only */

/* Driver for Genesys Logic GL9763E */

#include <console/console.h>
#include <device/device.h>
#include <device/path.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <device/pci_ids.h>
#include "gl9763e.h"

static void gl9763e_init(struct device *dev)
{
printk(BIOS_INFO, "GL9763E: init\n");
pci_dev_init(dev);

/* Set VHS (Vendor Header Space) to be writable */
pci_update_config32(dev, VHS, ~VHS_REV_MASK, VHS_REV_W);
/* Set single AXI request */
pci_or_config32(dev, SCR, SCR_AXI_REQ);
/* Disable L0s support */
pci_and_config32(dev, CFG_REG_2, ~CFG_REG_2_L0S);
/* Set SSC to 30000 ppm */
pci_update_config32(dev, PLL_CTL_2, ~PLL_CTL_2_MAX_SSC_MASK, MAX_SSC_30000PPM);
/* Enable SSC */
pci_or_config32(dev, PLL_CTL, PLL_CTL_SSC);
/* Set VHS to read-only */
pci_update_config32(dev, VHS, ~VHS_REV_MASK, VHS_REV_R);
}

static struct device_operations gl9763e_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.ops_pci = &pci_dev_ops_pci,
.init = gl9763e_init,
};

static const unsigned short pci_device_ids[] = {
PCI_DEVICE_ID_GLI_9763E,
0
};

static const struct pci_driver genesyslogic_gl9763e __pci_driver = {
.ops = &gl9763e_ops,
.vendor = PCI_VENDOR_ID_GLI,
.devices = pci_device_ids,
};

struct chip_operations drivers_generic_genesyslogic_ops = {
CHIP_NAME("Genesys Logic GL9763E")
};
23 changes: 23 additions & 0 deletions src/drivers/genesyslogic/gl9763e/gl9763e.h
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-only */

/* Definitions for Genesys Logic GL9763E */

#include <types.h>

#define VHS 0x884
#define VHS_REV_MASK (0xF << 16)
#define VHS_REV_R (0x0 << 16)
#define VHS_REV_M (0x1 << 16)
#define VHS_REV_W (0x2 << 16)
#define SCR 0x8E0
#define SCR_AXI_REQ BIT(9)

#define CFG_REG_2 0x8A4
#define CFG_REG_2_L0S BIT(11)

#define PLL_CTL 0x938
#define PLL_CTL_SSC BIT(19)

#define PLL_CTL_2 0x93C
#define PLL_CTL_2_MAX_SSC_MASK (0xFFFF << 16)
#define MAX_SSC_30000PPM (0xF5C3 << 16)
18 changes: 9 additions & 9 deletions src/drivers/i2c/at24rf08c/lenovo_serials.c
Expand Up @@ -45,7 +45,7 @@ static void at24rf08c_read_string_dev(struct device *dev, u8 start,
int t = at24rf08c_read_byte(dev, start + i);

if (t < 0x20 || t > 0x7f) {
memcpy(result, ERROR_STRING, sizeof (ERROR_STRING));
memcpy(result, ERROR_STRING, sizeof(ERROR_STRING));
return;
}
result[i] = t;
Expand All @@ -60,7 +60,7 @@ static void at24rf08c_read_string(u8 bank, u8 start, u8 len, char *result)
dev = at24rf08c_find_bank(bank);
if (dev == NULL) {
printk(BIOS_WARNING, "EEPROM not found\n");
memcpy(result, ERROR_STRING, sizeof (ERROR_STRING));
memcpy(result, ERROR_STRING, sizeof(ERROR_STRING));
return;
}

Expand All @@ -75,7 +75,7 @@ const char *smbios_mainboard_serial_number(void)
if (already_read)
return result;

memset(result, 0, sizeof (result));
memset(result, 0, sizeof(result));
at24rf08c_read_string(0, 0x2e, 7, result);

already_read = 1;
Expand All @@ -90,7 +90,7 @@ const char *lenovo_mainboard_partnumber(void)
if (already_read)
return result;

memset(result, 0, sizeof (result));
memset(result, 0, sizeof(result));
at24rf08c_read_string(0, 0x27, 7, result);

already_read = 1;
Expand Down Expand Up @@ -119,7 +119,7 @@ void smbios_system_set_uuid(u8 *uuid)
return;
}

memset(result, 0, sizeof (result));
memset(result, 0, sizeof(result));

dev = dev_find_slot_on_smbus(1, 0x56);
if (dev == NULL) {
Expand All @@ -141,7 +141,7 @@ void smbios_system_set_uuid(u8 *uuid)
break;
}
if (t < 0) {
memset(result, 0, sizeof (result));
memset(result, 0, sizeof(result));
break;
}
result[remap[i]] = t;
Expand All @@ -162,17 +162,17 @@ const char *smbios_mainboard_version(void)
if (already_read)
return result;

memset(result, 0, sizeof (result));
memset(result, 0, sizeof(result));

dev = at24rf08c_find_bank(2);
if (dev == NULL) {
memcpy(result, ERROR_STRING, sizeof (ERROR_STRING));
memcpy(result, ERROR_STRING, sizeof(ERROR_STRING));
return result;
}

len = at24rf08c_read_byte(dev, 0x26) - 2;
if (len < 0 || len > sizeof(result) - 1) {
memcpy(result, ERROR_STRING, sizeof (ERROR_STRING));
memcpy(result, ERROR_STRING, sizeof(ERROR_STRING));
return result;
}

Expand Down
2 changes: 1 addition & 1 deletion src/drivers/i2c/max98373/max98373.c
Expand Up @@ -25,7 +25,7 @@ static void max98373_fill_ssdt(const struct device *dev)
struct acpi_dp *dp;

if (!dev->enabled || !scope) {
printk(BIOS_ERR, "%s: dev not enabled", __func__);
printk(BIOS_ERR, "%s: dev not enabled\n", __func__);
return;
}

Expand Down
11 changes: 6 additions & 5 deletions src/drivers/intel/dptf/Kconfig
@@ -1,16 +1,17 @@
config DRIVERS_INTEL_DPTF
bool "Support runtime generation of Intel DPTF ACPI tables"
bool
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.

config DPTF_USE_EISA_HID
bool "If selected, use 'old' 7 character EISA IDs for DPTF _HID"
bool
depends on DRIVERS_INTEL_DPTF
default n
help
When selected, all DPTF devices will use the "old" style of
_HIDs, which are 7-character EISA IDs. Otherwise, it will use
the "new" style, which are regular 8-character _HIDs.
Prior to Tiger Lake, all DPTF devices used 7-character EISA
IDs. If selected, the 7-character _HIDs will be emitted,
otherwise, it will use the "new" style, which are regular
8-character _HIDs.
2 changes: 2 additions & 0 deletions src/drivers/intel/dptf/dptf.c
Expand Up @@ -209,9 +209,11 @@ static void write_options(const struct drivers_intel_dptf_config *config)
int i;

/* Fan options */
dptf_write_scope(DPTF_FAN);
dptf_write_fan_options(config->options.fan.fine_grained_control,
config->options.fan.step_size,
config->options.fan.low_speed_notify);
acpigen_pop_len(); /* Scope */

/* TSR options */
for (p = DPTF_TEMP_SENSOR_0, i = 0; p <= DPTF_TEMP_SENSOR_3; ++p, ++i) {
Expand Down
48 changes: 24 additions & 24 deletions src/drivers/intel/fsp1_1/romstage.c
Expand Up @@ -23,7 +23,7 @@
static void raminit_common(struct romstage_params *params)
{
bool s3wake;
struct region_device rdev;
size_t mrc_size;

post_code(0x32);

Expand All @@ -45,24 +45,31 @@ static void raminit_common(struct romstage_params *params)
/* Recovery mode does not use MRC cache */
printk(BIOS_DEBUG,
"Recovery mode: not using MRC cache.\n");
} else if (CONFIG(CACHE_MRC_SETTINGS)
&& (!mrc_cache_get_current(MRC_TRAINING_DATA,
params->fsp_version,
&rdev))) {
/* MRC cache found */
params->saved_data_size = region_device_sz(&rdev);
params->saved_data = rdev_mmap_full(&rdev);
} else {
/* Assume boot device is memory mapped. */
assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
} else if (s3wake) {
/* Waking from S3 and no cache. */
printk(BIOS_DEBUG,
"No MRC cache found in S3 resume path.\n");
post_code(POST_RESUME_FAILURE);
/* FIXME: A "system" reset is likely enough: */
full_reset();
} else {
printk(BIOS_DEBUG, "No MRC cache found.\n");

params->saved_data = NULL;
if (CONFIG(CACHE_MRC_SETTINGS))
params->saved_data =
mrc_cache_current_mmap_leak(MRC_TRAINING_DATA,
params->fsp_version,
&mrc_size);
if (params->saved_data) {
/* MRC cache found */
params->saved_data_size = mrc_size;

} else if (s3wake) {
/* Waking from S3 and no cache. */
printk(BIOS_DEBUG,
"No MRC cache "
"found in S3 resume path.\n");
post_code(POST_RESUME_FAILURE);
/* FIXME: A "system" reset is likely enough: */
full_reset();
} else {
printk(BIOS_DEBUG, "No MRC cache found.\n");
}
}
}

Expand Down Expand Up @@ -283,13 +290,6 @@ __weak void mainboard_add_dimm_info(
{
}

/* Get the memory configuration data */
__weak int mrc_cache_get_current(int type, uint32_t version,
struct region_device *rdev)
{
return -1;
}

/* Save the memory configuration data */
__weak int mrc_cache_stash_data(int type, uint32_t version,
const void *data, size_t size)
Expand Down
12 changes: 7 additions & 5 deletions src/drivers/intel/fsp2_0/Kconfig
Expand Up @@ -132,12 +132,14 @@ config FSP_USES_CB_STACK

config FSP_TEMP_RAM_SIZE
hex
depends on FSP_USES_CB_STACK
help
The amount of anticipated heap usage in CAR by FSP to setup HOB.
This configuration is applicable for FSP specification using shared
stack with coreboot/bootloader.
Sync this value with Platform FSP integration guide recommendation.
The amount of memory coreboot reserves for the FSP to use. In the
case of FSP 2.1 and newer that share the stack with coreboot instead
of having its own stack, this is the amount of anticipated heap usage
in CAR by FSP to setup HOB and needs to be the recommended value from
the Platform FSP integration guide. In the case of the FSP having its
own stack that will be placed in DRAM and not in CAR, this is the
amount of memory the FSP needs for its stack and heap.

config FSP2_0_USES_TPM_MRC_HASH
bool
Expand Down
1 change: 1 addition & 0 deletions src/drivers/intel/fsp2_0/Makefile.inc
Expand Up @@ -14,6 +14,7 @@ romstage-$(CONFIG_MMA) += mma_core.c
romstage-y += cbmem.c

ramstage-y += debug.c
ramstage-$(CONFIG_USE_INTEL_FSP_MP_INIT) += fsp_mpinit.c
ramstage-$(CONFIG_RUN_FSP_GOP) += graphics.c
ramstage-y += hand_off_block.c
ramstage-$(CONFIG_DISPLAY_FSP_HEADER) += header_display.c
Expand Down
14 changes: 14 additions & 0 deletions src/drivers/intel/fsp2_0/fsp_mpinit.c
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <fsp/api.h>
#include <intelblocks/mp_init.h>

/*
* As per FSP integration guide:
* If bootloader needs to take control of APs back, a full AP re-initialization is
* required after FSP-S is completed and control has been transferred back to bootloader
*/
void do_mpinit_after_fsp(void)
{
init_cpus();
}
7 changes: 3 additions & 4 deletions src/drivers/intel/fsp2_0/hand_off_block.c
Expand Up @@ -207,7 +207,7 @@ const void *fsp_find_extension_hob_by_guid(const uint8_t *guid, size_t *size)
return NULL;
}

static void display_fsp_version_info_hob(const void *hob, size_t size)
static void display_fsp_version_info_hob(const void *hob)
{
#if CONFIG(DISPLAY_FSP_VERSION_INFO)
const FIRMWARE_VERSION_INFO *fvi;
Expand All @@ -218,8 +218,7 @@ static void display_fsp_version_info_hob(const void *hob, size_t size)

fvi = (void *)&fvih[1];
str_ptr = (char *)((uintptr_t)fvi +
(fvih->Count * sizeof (FIRMWARE_VERSION_INFO)));
size -= sizeof(SMBIOS_STRUCTURE);
(fvih->Count * sizeof(FIRMWARE_VERSION_INFO)));

for (index = 0; index < fvih->Count; index++) {
cnt = strlen(str_ptr);
Expand Down Expand Up @@ -279,7 +278,7 @@ void fsp_display_fvi_version_hob(void)

if (fsp_guid_compare(hob_uuid, uuid_fv_info)) {
size = hob->length - (HOB_HEADER_LEN + 16);
display_fsp_version_info_hob(hob, size);
display_fsp_version_info_hob(hob);
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/drivers/intel/fsp2_0/include/fsp/api.h
Expand Up @@ -74,6 +74,13 @@ const struct cbmem_entry *soc_load_logo(FSPS_UPD *supd);
void soc_update_memory_params_for_mma(FSP_M_CONFIG *memory_cfg,
struct mma_config_param *mma_cfg);

/*
* As per FSP integration guide:
* If bootloader needs to take control of APs back, a full AP re-initialization is
* required after FSP-S is completed and control has been transferred back to bootloader
*/
void do_mpinit_after_fsp(void);

/*
* # DOCUMENTATION:
*
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/intel/fsp2_0/include/fsp/debug.h
Expand Up @@ -24,15 +24,15 @@ void fsp_verify_memory_init_hobs(void);
void fsp_print_header_info(const struct fsp_header *hdr);

/* Callbacks for displaying UPD parameters - place in a separate file
* that is conditionally build with CONFIG_DISPLAY_UPD_DATA.
* that is conditionally build with CONFIG(DISPLAY_UPD_DATA).
*/
void soc_display_fspm_upd_params(const FSPM_UPD *fspm_old_upd,
const FSPM_UPD *fspm_new_upd);
void soc_display_fsps_upd_params(const FSPS_UPD *fsps_old_upd,
const FSPS_UPD *fsps_new_upd);

/* Callbacks for displaying HOBs - place in a separate file that is
* conditionally build with CONFIG_DISPLAY_HOBS.
* conditionally build with CONFIG(DISPLAY_HOBS).
*/
const char *soc_get_hob_type_name(const struct hob_header *hob);
const char *soc_get_guid_name(const uint8_t *guid);
Expand Down
16 changes: 7 additions & 9 deletions src/drivers/intel/fsp2_0/memory_init.c
Expand Up @@ -93,8 +93,8 @@ static void do_fsp_post_memory_init(bool s3wake, uint32_t fsp_version)

static void fsp_fill_mrc_cache(FSPM_ARCH_UPD *arch_upd, uint32_t fsp_version)
{
struct region_device rdev;
void *data;
size_t mrc_size;

arch_upd->NvsBufferPtr = NULL;

Expand All @@ -113,25 +113,22 @@ static void fsp_fill_mrc_cache(FSPM_ARCH_UPD *arch_upd, uint32_t fsp_version)
return;
}

if (mrc_cache_get_current(MRC_TRAINING_DATA, fsp_version, &rdev) < 0)
return;

/* Assume boot device is memory mapped. */
assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
data = rdev_mmap_full(&rdev);

data = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, fsp_version,
&mrc_size);
if (data == NULL)
return;

if (CONFIG(FSP2_0_USES_TPM_MRC_HASH) &&
!mrc_cache_verify_hash(data, region_device_sz(&rdev)))
!mrc_cache_verify_hash(data, mrc_size))
return;

/* MRC cache found */
arch_upd->NvsBufferPtr = data;

printk(BIOS_SPEW, "MRC cache found, size %zx\n",
region_device_sz(&rdev));
printk(BIOS_SPEW, "MRC cache found, size %zx\n", mrc_size);
}

static enum cb_err check_region_overlap(const struct memranges *ranges,
Expand Down Expand Up @@ -184,8 +181,9 @@ static enum cb_err fsp_fill_common_arch_params(FSPM_ARCH_UPD *arch_upd,
* top and does not reinitialize stack pointer. The parameters passed
* as StackBase and StackSize are actually for temporary RAM and HOBs
* and are not related to FSP stack at all.
* Non-CAR FSP 2.0 platforms pass a DRAM location for the FSP stack.
*/
if (CONFIG(FSP_USES_CB_STACK)) {
if (CONFIG(FSP_USES_CB_STACK) || !ENV_CACHE_AS_RAM) {
arch_upd->StackBase = temp_ram;
arch_upd->StackSize = sizeof(temp_ram);
} else if (setup_fsp_stack_frame(arch_upd, memmap)) {
Expand Down
12 changes: 11 additions & 1 deletion src/drivers/intel/fsp2_0/ppi/mp_service_ppi.c
Expand Up @@ -10,6 +10,7 @@
#include <intelblocks/mp_init.h>

#define BSP_CPU_SLOT 0
#define SINGLE_CHIP_PACKAGE 0

static efi_return_status_t mp_get_number_of_processors(const
efi_pei_services **ignored1, efi_pei_mp_services_ppi *ignored2,
Expand All @@ -31,6 +32,8 @@ static efi_return_status_t mp_get_processor_info(const
efi_uintn_t processor_number,
efi_processor_information *processor_info_buffer)
{
unsigned int num_virt_cores, num_phys_cores;

if (cpu_index() < 0)
return FSP_DEVICE_ERROR;

Expand All @@ -48,7 +51,14 @@ static efi_return_status_t mp_get_processor_info(const
if (processor_number == BSP_CPU_SLOT)
processor_info_buffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;

/* TODO: Fill EFI_CPU_PHYSICAL_LOCATION structure information */
/* Fill EFI_CPU_PHYSICAL_LOCATION structure information */
cpu_read_topology(&num_phys_cores, &num_virt_cores);

/* FSP will add one to the value in this Package field */
processor_info_buffer->Location.Package = SINGLE_CHIP_PACKAGE;
processor_info_buffer->Location.Core = num_phys_cores;
processor_info_buffer->Location.Thread = num_virt_cores;

return FSP_SUCCESS;
}

Expand Down
4 changes: 4 additions & 0 deletions src/drivers/intel/fsp2_0/silicon_init.c
Expand Up @@ -127,6 +127,10 @@ static void do_silicon_init(struct fsp_header *hdr)
fsp_debug_after_silicon_init(status);
fsps_return_value_handler(FSP_SILICON_INIT_API, status);

/* Reinitialize CPUs if FSP-S has done MP Init */
if (CONFIG(USE_INTEL_FSP_MP_INIT))
do_mpinit_after_fsp();

if (!CONFIG(PLATFORM_USES_FSP2_2))
return;

Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/fsp2_0/util.c
Expand Up @@ -8,7 +8,6 @@
#include <commonlib/fsp.h>
#include <console/console.h>
#include <fsp/util.h>
#include <lib.h>
#include <string.h>
#include <types.h>

Expand Down
22 changes: 11 additions & 11 deletions src/drivers/intel/gma/vbt.c
Expand Up @@ -15,31 +15,31 @@ static size_t generate_vbt(const struct i915_gpu_controller_info *const conf,
{
u8 *ptr;

memset(head, 0, sizeof (*head));
memset(head, 0, sizeof(*head));

memset(head->signature, ' ', sizeof (head->signature));
memset(head->signature, ' ', sizeof(head->signature));
memcpy(head->signature, idstr,
MIN(strlen(idstr), sizeof (head->signature)));
MIN(strlen(idstr), sizeof(head->signature)));
head->version = 100;
head->header_size = sizeof (*head);
head->bdb_offset = sizeof (*head);
head->header_size = sizeof(*head);
head->bdb_offset = sizeof(*head);

struct bdb_header *const bdb_head = (struct bdb_header *)(head + 1);
memset(bdb_head, 0, sizeof (*bdb_head));
memset(bdb_head, 0, sizeof(*bdb_head));
memcpy(bdb_head->signature, "BIOS_DATA_BLOCK ", 16);
bdb_head->version = 0xa8;
bdb_head->header_size = sizeof (*bdb_head);
bdb_head->header_size = sizeof(*bdb_head);

ptr = (u8 *)(bdb_head + 1);

ptr[0] = BDB_GENERAL_FEATURES;
ptr[1] = sizeof (struct bdb_general_features);
ptr[2] = sizeof (struct bdb_general_features) >> 8;
ptr[1] = sizeof(struct bdb_general_features);
ptr[2] = sizeof(struct bdb_general_features) >> 8;
ptr += 3;

struct bdb_general_features *const genfeat =
(struct bdb_general_features *)ptr;
memset(genfeat, 0, sizeof (*genfeat));
memset(genfeat, 0, sizeof(*genfeat));
genfeat->panel_fitting = 3;
genfeat->flexaim = 1;
genfeat->download_ext_vbt = 1;
Expand All @@ -50,7 +50,7 @@ static size_t generate_vbt(const struct i915_gpu_controller_info *const conf,
genfeat->int_crt_support = 1;
genfeat->dp_ssc_enb = 1;

ptr += sizeof (*genfeat);
ptr += sizeof(*genfeat);

bdb_head->bdb_size = ptr - (u8 *)bdb_head;
head->vbt_size = ptr - (u8 *)head;
Expand Down
396 changes: 345 additions & 51 deletions src/drivers/intel/mipi_camera/camera.c

Large diffs are not rendered by default.

26 changes: 24 additions & 2 deletions src/drivers/intel/mipi_camera/chip.h
Expand Up @@ -13,6 +13,7 @@
#define MAX_CLK_CONFIGS 2
#define MAX_GPIO_CONFIGS 4
#define MAX_PWR_OPS 5
#define MAX_GUARDED_RESOURCES 10

#define SEQ_OPS_CLK_ENABLE(ind, delay) \
{ .type = IMGCLK, .index = (ind), .action = ENABLE, .delay_ms = (delay) }
Expand Down Expand Up @@ -70,15 +71,36 @@ enum intel_power_action_type {
};

enum ctrl_type {
IMGCLK = 1,
UNKNOWN_CTRL,
IMGCLK,
GPIO
};

enum action_type {
ENABLE = 1,
UNKNOWN_ACTION,
ENABLE,
DISABLE
};

struct camera_resource {
uint8_t type;
uint8_t id;
};

struct camera_resource_manager {
uint8_t cnt;
struct camera_resource resource[MAX_GUARDED_RESOURCES];
};

struct resource_config {
enum action_type action;
enum ctrl_type type;
union {
const struct clk_config *clk_conf;
const struct gpio_config *gpio_conf;
};
};

struct clk_config {
/* IMGCLKOUT_x being used for a port */
uint8_t clknum;
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/intel/soundwire/soundwire.h
Expand Up @@ -4,7 +4,7 @@
#define __DRIVERS_INTEL_SOUNDWIRE_H__

#include <device/soundwire.h>
#include <stdint.h>
#include <types.h>

/**
* enum intel_soundwire_quirk - Quirks for controller master links.
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/intel/wifi/Kconfig
Expand Up @@ -2,7 +2,7 @@ config DRIVERS_INTEL_WIFI
bool "Support Intel PCI-e WiFi adapters"
depends on PCI
default y if PCIEXP_PLUGIN_SUPPORT
select DRIVERS_GENERIC_WIFI if HAVE_ACPI_TABLES
select DRIVERS_WIFI_GENERIC if HAVE_ACPI_TABLES
help
When enabled, add identifiers in ACPI and SMBIOS tables to
make OS drivers work with certain Intel PCI-e WiFi chipsets.
8 changes: 4 additions & 4 deletions src/drivers/intel/wifi/wifi.c
Expand Up @@ -8,7 +8,7 @@
#include <smbios.h>
#include <string.h>
#include "chip.h"
#include "drivers/wifi/generic_wifi.h"
#include "drivers/wifi/generic/chip.h"

#define PMCS_DR 0xcc
#define PME_STS (1 << 15)
Expand Down Expand Up @@ -50,14 +50,14 @@ static int smbios_write_wifi(struct device *dev, int *handle,
static void intel_wifi_fill_ssdt(const struct device *dev)
{
struct drivers_intel_wifi_config *config = dev->chip_info;
struct generic_wifi_config generic_config;
struct drivers_wifi_generic_config generic_config;

if (config) {
generic_config.wake = config->wake;
/* By default, all intel wifi chips wake from S3 */
generic_config.maxsleep = 3;
}
generic_wifi_fill_ssdt(dev, config ? &generic_config : NULL);
wifi_generic_fill_ssdt(dev, config ? &generic_config : NULL);
}
#endif

Expand All @@ -83,7 +83,7 @@ struct device_operations device_ops = {
#endif
.ops_pci = &pci_dev_ops_pci,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_name = generic_wifi_acpi_name,
.acpi_name = wifi_generic_acpi_name,
.acpi_fill_ssdt = intel_wifi_fill_ssdt,
#endif
};
Expand Down
10 changes: 10 additions & 0 deletions src/drivers/ipmi/ocp/Kconfig
@@ -0,0 +1,10 @@
config IPMI_OCP
bool
default n
help
This implements OCP specific IPMI command

config IPMI_OCP_MANU_ID
hex
default 0x0
depends on IPMI_OCP
1 change: 1 addition & 0 deletions src/drivers/ipmi/ocp/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_IPMI_OCP) += ipmi_ocp.c
173 changes: 173 additions & 0 deletions src/drivers/ipmi/ocp/ipmi_ocp.c
@@ -0,0 +1,173 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Place in devicetree.cb:
*
* chip drivers/ipmi/ocp # OCP specific IPMI porting
device pnp ca2.1 on end
* end
*/

#include <console/console.h>
#include <device/device.h>
#include <device/pnp.h>
#include <string.h>
#include <intelblocks/cpulib.h>
#include <arch/cpu.h>
#include "chip.h"
#include "drivers/ipmi/ipmi_kcs.h"
#include "ipmi_ocp.h"

static int ipmi_set_processor_information_param1(struct device *dev)
{
int ret;
struct ipmi_processor_info_param1_req req1 = {0};
struct ipmi_rsp rsp;
int mfid = CONFIG_IPMI_OCP_MANU_ID;

memcpy(&req1.data.manufacturer_id, &mfid, 3);
printk(BIOS_DEBUG, "IPMI BMC manufacturer id: %02x%02x%02x\n",
req1.data.manufacturer_id[2], req1.data.manufacturer_id[1],
req1.data.manufacturer_id[0]);

req1.data.index = 0;
req1.data.parameter_selector = 1;

/* Get processor name. */
fill_processor_name(req1.product_name);
printk(BIOS_DEBUG, "IPMI BMC CPU NAME: %s.\n", req1.product_name);

ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM_COMMON, 0,
IPMI_BMC_SET_PROCESSOR_INFORMATION, (u8 *) &req1,
sizeof(req1), (u8 *) &rsp, sizeof(rsp));

if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
printk(BIOS_ERR, "IPMI BMC: %s command failed (ret=%d rsp=0x%x)\n",
__func__, ret, rsp.completion_code);
return CB_ERR;
}
return CB_SUCCESS;
}

static int ipmi_set_processor_information_param2(struct device *dev)
{
int ret;
struct ipmi_processor_info_param2_req req2 = {0};
struct ipmi_rsp rsp;
uint8_t stepping_id;
int mfid = CONFIG_IPMI_OCP_MANU_ID;
unsigned int core_count, thread_count;
struct cpuinfo_x86 c;

memcpy(&req2.data.manufacturer_id, &mfid, 3);
printk(BIOS_DEBUG, "IPMI BMC manufacturer id: %02x%02x%02x\n",
req2.data.manufacturer_id[2], req2.data.manufacturer_id[1],
req2.data.manufacturer_id[0]);

req2.data.index = 0;
req2.data.parameter_selector = 2;

/* Get core number and thread number. */
cpu_read_topology(&core_count, &thread_count);
req2.core_number = core_count;
req2.thread_number = thread_count;
printk(BIOS_DEBUG, "IPMI BMC CPU has %u cores, %u threads enabled.\n",
req2.core_number, req2.thread_number);

/* Get processor frequency. */
req2.processor_freq = 100 * cpu_get_max_ratio();
printk(BIOS_DEBUG, "IPMI BMC CPU frequency is %u MHz.\n",
req2.processor_freq);

/* Get revision. */
get_fms(&c, cpuid_eax(1));
stepping_id = c.x86_mask;
printk(BIOS_DEBUG, "IPMI BMC CPU stepping id is %x.\n", stepping_id);
switch (stepping_id) {
/* TBD */
case 0x0a:
req2.revision[0] = 'A';
req2.revision[1] = '0';
break;
default:
req2.revision[0] = 'X';
req2.revision[1] = 'X';
}

ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_OEM_COMMON, 0,
IPMI_BMC_SET_PROCESSOR_INFORMATION, (u8 *) &req2,
sizeof(req2), (u8 *) &rsp, sizeof(rsp));

if (ret < sizeof(struct ipmi_rsp) || rsp.completion_code) {
printk(BIOS_ERR, "IPMI: %s command failed (ret=%d rsp=0x%x)\n",
__func__, ret, rsp.completion_code);
return CB_ERR;
}
return CB_SUCCESS;
}

static void ipmi_set_processor_information(struct device *dev)
{
if (ipmi_set_processor_information_param1(dev))
printk(BIOS_ERR, "IPMI BMC set param 1 processor info failed\n");

if (ipmi_set_processor_information_param2(dev))
printk(BIOS_ERR, "IPMI BMC set param 2 processor info failed\n");
}

static void ipmi_ocp_init(struct device *dev)
{
/* Add OCP specific IPMI command */
}

static void ipmi_ocp_final(struct device *dev)
{
/* Add OCP specific IPMI command */

/* Send processor information */
ipmi_set_processor_information(dev);
}

static void ipmi_set_resources(struct device *dev)
{
struct resource *res;

for (res = dev->resource_list; res; res = res->next) {
if (!(res->flags & IORESOURCE_ASSIGNED))
continue;

res->flags |= IORESOURCE_STORED;
report_resource_stored(dev, res, "");
}
}

static void ipmi_read_resources(struct device *dev)
{
struct resource *res = new_resource(dev, 0);
res->base = dev->path.pnp.port;
res->size = 2;
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
}

static struct device_operations ops = {
.read_resources = ipmi_read_resources,
.set_resources = ipmi_set_resources,
.init = ipmi_ocp_init,
.final = ipmi_ocp_final,
};

static void enable_dev(struct device *dev)
{
if (dev->path.type != DEVICE_PATH_PNP)
printk(BIOS_ERR, "%s: Unsupported device type\n",
dev_path(dev));
else if (dev->path.pnp.port & 1)
printk(BIOS_ERR, "%s: Base address needs to be aligned to 2\n",
dev_path(dev));
else
dev->ops = &ops;
}

struct chip_operations drivers_ipmi_ocp_ops = {
CHIP_NAME("IPMI OCP")
.enable_dev = enable_dev,
};
36 changes: 36 additions & 0 deletions src/drivers/ipmi/ocp/ipmi_ocp.h
@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef __IPMI_OCP_H
#define __IPMI_OCP_H

#include <cpu/x86/msr.h>
#include <cpu/x86/name.h>
#include "drivers/ipmi/ipmi_kcs.h"

#define IPMI_NETFN_OEM_COMMON 0x36
#define IPMI_BMC_SET_PROCESSOR_INFORMATION 0x10
#define IPMI_BMC_GET_PROCESSOR_INFORMATION 0x11

#define MSR_CORE_THREAD_COUNT 0x35
#define MSR_PLATFORM_INFO 0xce

struct ipmi_processor_info_req {
uint8_t manufacturer_id[3];
uint8_t index;
uint8_t parameter_selector;
} __packed;

struct ipmi_processor_info_param1_req {
struct ipmi_processor_info_req data;
char product_name[48];
} __packed;

struct ipmi_processor_info_param2_req {
struct ipmi_processor_info_req data;
uint8_t core_number;
uint16_t thread_number;
uint16_t processor_freq;
char revision[2];
} __packed;

#endif
180 changes: 114 additions & 66 deletions src/drivers/mrc_cache/mrc_cache.c
Expand Up @@ -109,41 +109,6 @@ static const struct cache_region *lookup_region_type(int type)
return NULL;
}

int mrc_cache_stash_data(int type, uint32_t version, const void *data,
size_t size)
{
const struct cache_region *cr;
size_t cbmem_size;
struct mrc_metadata *md;

cr = lookup_region_type(type);
if (cr == NULL) {
printk(BIOS_ERR, "MRC: failed to add to cbmem for type %d.\n",
type);
return -1;
}

cbmem_size = sizeof(*md) + size;

md = cbmem_add(cr->cbmem_id, cbmem_size);

if (md == NULL) {
printk(BIOS_ERR, "MRC: failed to add '%s' to cbmem.\n",
cr->name);
return -1;
}

memset(md, 0, sizeof(*md));
md->signature = MRC_DATA_SIGNATURE;
md->data_size = size;
md->version = version;
md->data_checksum = compute_ip_checksum(data, size);
md->header_checksum = compute_ip_checksum(md, sizeof(*md));
memcpy(&md[1], data, size);

return 0;
}

static const struct cache_region *lookup_region(struct region *r, int type)
{
const struct cache_region *cr;
Expand Down Expand Up @@ -204,23 +169,16 @@ static int mrc_header_valid(struct region_device *rdev, struct mrc_metadata *md)
return 0;
}

static int mrc_data_valid(const struct region_device *rdev,
const struct mrc_metadata *md)
static int mrc_data_valid(const struct mrc_metadata *md,
void *data, size_t data_size)
{
void *data;
uint16_t checksum;
const size_t md_size = sizeof(*md);
const size_t data_size = md->data_size;

data = rdev_mmap(rdev, md_size, data_size);
if (data == NULL) {
printk(BIOS_ERR, "MRC: mmap failure on data verification.\n");
if (md->data_size != data_size)
return -1;
}

checksum = compute_ip_checksum(data, data_size);

rdev_munmap(rdev, data);
if (md->data_checksum != checksum) {
printk(BIOS_ERR, "MRC: data checksum mismatch: %x vs %x\n",
md->data_checksum, checksum);
Expand All @@ -230,7 +188,7 @@ static int mrc_data_valid(const struct region_device *rdev,
return 0;
}

static int mrc_cache_latest(const char *name,
static int mrc_cache_get_latest_slot_info(const char *name,
const struct region_device *backing_rdev,
struct mrc_metadata *md,
struct region_file *cache_file,
Expand Down Expand Up @@ -260,25 +218,19 @@ static int mrc_cache_latest(const char *name,
return fail_bad_data ? -1 : 0;
}

/* Validate Data */
if (mrc_data_valid(rdev, md) < 0) {
printk(BIOS_ERR, "MRC: invalid data in '%s'\n", name);
return fail_bad_data ? -1 : 0;
}

return 0;
}

int mrc_cache_get_current(int type, uint32_t version,
struct region_device *rdev)
static int mrc_cache_find_current(int type, uint32_t version,
struct region_device *rdev,
struct mrc_metadata *md)
{
const struct cache_region *cr;
struct region region;
struct region_device read_rdev;
struct region_file cache_file;
struct mrc_metadata md;
size_t data_size;
const size_t md_size = sizeof(md);
const size_t md_size = sizeof(*md);
const bool fail_bad_data = true;

cr = lookup_region(&region, type);
Expand All @@ -289,21 +241,75 @@ int mrc_cache_get_current(int type, uint32_t version,
if (boot_device_ro_subregion(&region, &read_rdev) < 0)
return -1;

if (mrc_cache_latest(cr->name, &read_rdev, &md, &cache_file, rdev,
fail_bad_data) < 0)
if (mrc_cache_get_latest_slot_info(cr->name,
&read_rdev,
md,
&cache_file,
rdev,
fail_bad_data) < 0)
return -1;

if (version != md.version) {
if (version != md->version) {
printk(BIOS_INFO, "MRC: version mismatch: %x vs %x\n",
md.version, version);
md->version, version);
return -1;
}

/* Re-size rdev to only contain the data. i.e. remove metadata. */
data_size = md.data_size;
data_size = md->data_size;
return rdev_chain(rdev, rdev, md_size, data_size);
}

int mrc_cache_load_current(int type, uint32_t version, void *buffer,
size_t buffer_size)
{
struct region_device rdev;
struct mrc_metadata md;
size_t data_size;

if (mrc_cache_find_current(type, version, &rdev, &md) < 0)
return -1;

data_size = region_device_sz(&rdev);
if (buffer_size < data_size)
return -1;

if (rdev_readat(&rdev, buffer, 0, data_size) != data_size)
return -1;

if (mrc_data_valid(&md, buffer, data_size) < 0)
return -1;

return 0;
}

void *mrc_cache_current_mmap_leak(int type, uint32_t version,
size_t *data_size)
{
struct region_device rdev;
void *data;
size_t region_device_size;
struct mrc_metadata md;

if (mrc_cache_find_current(type, version, &rdev, &md) < 0)
return NULL;

region_device_size = region_device_sz(&rdev);
if (data_size)
*data_size = region_device_size;
data = rdev_mmap_full(&rdev);

if (data == NULL) {
printk(BIOS_INFO, "MRC: mmap failure.\n");
return NULL;
}

if (mrc_data_valid(&md, data, region_device_size) < 0)
return NULL;

return data;
}

static bool mrc_cache_needs_update(const struct region_device *rdev,
const struct cbmem_entry *to_be_updated)
{
Expand Down Expand Up @@ -392,8 +398,17 @@ static void update_mrc_cache_by_type(int type)
if (backing_rdev == NULL)
return;

if (mrc_cache_latest(cr->name, backing_rdev, &md, &cache_file,
&latest_rdev, fail_bad_data) < 0)
/* Note that mrc_cache_get_latest_slot_info doesn't check the
* validity of the current slot. If the slot is invalid,
* we'll overwrite it anyway when we update the mrc_cache.
*/
if (mrc_cache_get_latest_slot_info(cr->name,
backing_rdev,
&md,
&cache_file,
&latest_rdev,
fail_bad_data) < 0)

return;

if (!mrc_cache_needs_update(&latest_rdev, to_be_updated)) {
Expand Down Expand Up @@ -447,15 +462,13 @@ static int nvm_is_write_protected(void)
/* Apply protection to a range of flash */
static int nvm_protect(const struct region *r)
{
const struct spi_flash *flash = boot_device_spi_flash();

if (!CONFIG(MRC_SETTINGS_PROTECT))
return 0;

if (!CONFIG(BOOT_DEVICE_SPI_FLASH))
return 0;

return spi_flash_ctrlr_protect_region(flash, r, WRITE_PROTECT);
return spi_flash_ctrlr_protect_region(boot_device_spi_flash(), r, WRITE_PROTECT);
}

/* Protect mrc region with a Protected Range Register */
Expand Down Expand Up @@ -548,6 +561,41 @@ static void update_mrc_cache(void *unused)
protect_mrc_region();
}

int mrc_cache_stash_data(int type, uint32_t version, const void *data,
size_t size)
{
const struct cache_region *cr;
size_t cbmem_size;
struct mrc_metadata *md;

cr = lookup_region_type(type);
if (cr == NULL) {
printk(BIOS_ERR, "MRC: failed to add to cbmem for type %d.\n",
type);
return -1;
}

cbmem_size = sizeof(*md) + size;

md = cbmem_add(cr->cbmem_id, cbmem_size);

if (md == NULL) {
printk(BIOS_ERR, "MRC: failed to add '%s' to cbmem.\n",
cr->name);
return -1;
}

memset(md, 0, sizeof(*md));
md->signature = MRC_DATA_SIGNATURE;
md->data_size = size;
md->version = version;
md->data_checksum = compute_ip_checksum(data, size);
md->header_checksum = compute_ip_checksum(md, sizeof(*md));
memcpy(&md[1], data, size);

return 0;
}

/*
* Ensures MRC training data is stored into SPI after PCI enumeration is done.
* Some implementations may require this to be later than others.
Expand Down
3 changes: 1 addition & 2 deletions src/drivers/pc80/rtc/mc146818rtc.c
Expand Up @@ -6,7 +6,6 @@
#include <fallback.h>
#include <version.h>
#include <console/console.h>
#include <option.h>
#include <pc80/mc146818rtc.h>
#include <rtc.h>
#include <security/vboot/vbnv.h>
Expand Down Expand Up @@ -144,7 +143,7 @@ static void cmos_init_vbnv(bool invalid)
uint8_t vbnv[VBOOT_VBNV_BLOCK_SIZE];

/* __cmos_init() will clear vbnv contents when a known rtc failure
occurred with !CONFIG_USE_OPTION_TABLE. However, __cmos_init() may
occurred with !CONFIG(USE_OPTION_TABLE). However, __cmos_init() may
clear vbnv data for other internal reasons. For that, always back up
the vbnv contents and conditionally save them when __cmos_init()
indicates CMOS was cleared. */
Expand Down
1 change: 0 additions & 1 deletion src/drivers/pc80/rtc/mc146818rtc_boot.c
Expand Up @@ -2,7 +2,6 @@

#include <stdint.h>
#include <console/console.h>
#include <option.h>
#include <pc80/mc146818rtc.h>
#include <fallback.h>

Expand Down