Patch queue for efi - 2016-10-19
Highlights this time around: - Add run time service (power control) support for PSCI (fixed in v3) - Add efi gop pointer exposure - SMBIOS support for EFI (on ARM) - efi pool memory unmap support (needed for 4.8) - initial x86 efi payload support (fixed up in v2) - various bug fixes -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJYBx6vAAoJECszeR4D/txgiNwQAJAcdx7m54D+c3juXR3wT3WR 9A0NIkyY9M/lwdG8MRZubaXV6b7s1iZhROvEGN6sZVKe+hR+c8KWbjNC34i/Mzd2 SLFTax+EWiNogSwPxBUG4R5rpPb4UFDreG9ava7L2A07E/zmXlOTJMj8YBPWKUMf FltmpLFm4lBpm5l/e47f1hotUnRcvwr44dp09G4hjYGh8cdusHeKebwlkyCPhhH7 GwYDI4Reg8dHQqbKNSPaAeK97zE30H+w6kzF4DH1Dl4W9gI9fIlJC3XVajt9qoDz 8CLAMr4ptqnYZlVq+LYPpNDFG9Pkpb78ksCBmolbs/xSo9Nd0s0WRQA6Jvg5oSpu aVDTJW3qWs3I1zfIDb0maX0yKer8QAm3D99zURxoyjALjNIS4++Tpa6TbgH/KvoQ Si+ExfGc+MsWFS9K2FMp6ukDhuPypirRF5VsliSXK7kwg2QWQ2DMS9LLgabK3y2e RxURzy9SJZf6NL7bUmCxvqdQd+S0+5sLJuc8n5sobiBRkvpmABHSelKKDg87C9OW IYDNI4iHZ1hJZb37Z2LO7R+PAUIX+vbRitnzWSXfXGNstR0Q48I4Lg2Ud1j7xkr2 +uUB0wqbAksaRnDfNNod6hNqBmgueJFK9eVvE2PP1Pl6B83sc6yBDgMNjngQ6hia 7nv3bhAqrnMTPoQkN7C+ =peNm -----END PGP SIGNATURE----- Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot Patch queue for efi - 2016-10-19 Highlights this time around: - Add run time service (power control) support for PSCI (fixed in v3) - Add efi gop pointer exposure - SMBIOS support for EFI (on ARM) - efi pool memory unmap support (needed for 4.8) - initial x86 efi payload support (fixed up in v2) - various bug fixes Signed-off-by: Tom Rini <trini@konsulko.com> Conflicts: include/tables_csum.h
This commit is contained in:
commit
3431b392ad
@ -21,4 +21,22 @@ config ARMV8_SPIN_TABLE
|
||||
- Reserve the code for the spin-table and the release address
|
||||
via a /memreserve/ region in the Device Tree.
|
||||
|
||||
config PSCI_RESET
|
||||
bool "Use PSCI for reset and shutdown"
|
||||
default y
|
||||
depends on !ARCH_EXYNOS7 && !ARCH_BCM283X && !TARGET_LS2080A_EMU && \
|
||||
!TARGET_LS2080A_SIMU && !TARGET_LS2080AQDS && \
|
||||
!TARGET_LS2080ARDB && !TARGET_LS1012AQDS && \
|
||||
!TARGET_LS1012ARDB && !TARGET_LS1012AFRDM && \
|
||||
!TARGET_LS1043ARDB && !ARCH_UNIPHIER && !ARCH_SNAPDRAGON && \
|
||||
!TARGET_S32V234EVB
|
||||
help
|
||||
Most armv8 systems have PSCI support enabled in EL3, either through
|
||||
ARM Trusted Firmware or other firmware.
|
||||
|
||||
On these systems, we do not need to implement system reset manually,
|
||||
but can instead rely on higher level firmware to deal with it.
|
||||
|
||||
Select Y here to make use of PSCI calls for system reset
|
||||
|
||||
endif
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <asm-offsets.h>
|
||||
#include <config.h>
|
||||
#include <efi_loader.h>
|
||||
#include <version.h>
|
||||
#include <asm/macro.h>
|
||||
#include <asm/psci.h>
|
||||
@ -17,7 +18,7 @@
|
||||
* x0~x7: input arguments
|
||||
* x0~x3: output arguments
|
||||
*/
|
||||
void hvc_call(struct pt_regs *args)
|
||||
static void __efi_runtime hvc_call(struct pt_regs *args)
|
||||
{
|
||||
asm volatile(
|
||||
"ldr x0, %0\n"
|
||||
@ -51,7 +52,7 @@ void hvc_call(struct pt_regs *args)
|
||||
* x0~x3: output arguments
|
||||
*/
|
||||
|
||||
void smc_call(struct pt_regs *args)
|
||||
void __efi_runtime smc_call(struct pt_regs *args)
|
||||
{
|
||||
asm volatile(
|
||||
"ldr x0, %0\n"
|
||||
@ -75,13 +76,21 @@ void smc_call(struct pt_regs *args)
|
||||
"x16", "x17");
|
||||
}
|
||||
|
||||
void __noreturn psci_system_reset(bool conduit_smc)
|
||||
/*
|
||||
* For now, all systems we support run at least in EL2 and thus
|
||||
* trigger PSCI calls to EL3 using SMC. If anyone ever wants to
|
||||
* use PSCI on U-Boot running below a hypervisor, please detect
|
||||
* this and set the flag accordingly.
|
||||
*/
|
||||
static const __efi_runtime_data bool use_smc_for_psci = true;
|
||||
|
||||
void __noreturn __efi_runtime psci_system_reset(void)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_RESET;
|
||||
|
||||
if (conduit_smc)
|
||||
if (use_smc_for_psci)
|
||||
smc_call(®s);
|
||||
else
|
||||
hvc_call(®s);
|
||||
@ -89,3 +98,45 @@ void __noreturn psci_system_reset(bool conduit_smc)
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void __noreturn __efi_runtime psci_system_off(void)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
regs.regs[0] = ARM_PSCI_0_2_FN_SYSTEM_OFF;
|
||||
|
||||
if (use_smc_for_psci)
|
||||
smc_call(®s);
|
||||
else
|
||||
hvc_call(®s);
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PSCI_RESET
|
||||
void reset_misc(void)
|
||||
{
|
||||
psci_system_reset();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER
|
||||
void __efi_runtime EFIAPI efi_reset_system(
|
||||
enum efi_reset_type reset_type,
|
||||
efi_status_t reset_status,
|
||||
unsigned long data_size, void *reset_data)
|
||||
{
|
||||
switch (reset_type) {
|
||||
case EFI_RESET_COLD:
|
||||
case EFI_RESET_WARM:
|
||||
psci_system_reset();
|
||||
break;
|
||||
case EFI_RESET_SHUTDOWN:
|
||||
psci_system_off();
|
||||
break;
|
||||
}
|
||||
|
||||
while (1) { }
|
||||
}
|
||||
#endif /* CONFIG_EFI_LOADER */
|
||||
#endif /* CONFIG_PSCI_RESET */
|
||||
|
@ -106,15 +106,6 @@ void smp_kick_all_cpus(void);
|
||||
|
||||
void flush_l3_cache(void);
|
||||
|
||||
/*
|
||||
*Issue a hypervisor call in accordance with ARM "SMC Calling convention",
|
||||
* DEN0028A
|
||||
*
|
||||
* @args: input and output arguments
|
||||
*
|
||||
*/
|
||||
void hvc_call(struct pt_regs *args);
|
||||
|
||||
/*
|
||||
*Issue a secure monitor call in accordance with ARM "SMC Calling convention",
|
||||
* DEN0028A
|
||||
@ -124,7 +115,8 @@ void hvc_call(struct pt_regs *args);
|
||||
*/
|
||||
void smc_call(struct pt_regs *args);
|
||||
|
||||
void __noreturn psci_system_reset(bool smc);
|
||||
void __noreturn psci_system_reset(void);
|
||||
void __noreturn psci_system_off(void);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
@ -43,7 +43,7 @@ void dram_init_banksize(void)
|
||||
|
||||
void reset_cpu(ulong addr)
|
||||
{
|
||||
psci_system_reset(true);
|
||||
psci_system_reset();
|
||||
}
|
||||
|
||||
static struct mm_region gxbb_mem_map[] = {
|
||||
|
0
arch/avr32/include/asm/linkage.h
Normal file
0
arch/avr32/include/asm/linkage.h
Normal file
0
arch/m68k/include/asm/linkage.h
Normal file
0
arch/m68k/include/asm/linkage.h
Normal file
0
arch/microblaze/include/asm/linkage.h
Normal file
0
arch/microblaze/include/asm/linkage.h
Normal file
0
arch/mips/include/asm/linkage.h
Normal file
0
arch/mips/include/asm/linkage.h
Normal file
0
arch/nios2/include/asm/linkage.h
Normal file
0
arch/nios2/include/asm/linkage.h
Normal file
0
arch/openrisc/include/asm/linkage.h
Normal file
0
arch/openrisc/include/asm/linkage.h
Normal file
0
arch/sandbox/include/asm/linkage.h
Normal file
0
arch/sandbox/include/asm/linkage.h
Normal file
0
arch/sh/include/asm/linkage.h
Normal file
0
arch/sh/include/asm/linkage.h
Normal file
0
arch/sparc/include/asm/linkage.h
Normal file
0
arch/sparc/include/asm/linkage.h
Normal file
@ -461,33 +461,6 @@ config GENERATE_ACPI_TABLE
|
||||
by the operating system. It defines platform-independent interfaces
|
||||
for configuration and power management monitoring.
|
||||
|
||||
config GENERATE_SMBIOS_TABLE
|
||||
bool "Generate an SMBIOS (System Management BIOS) table"
|
||||
default y
|
||||
help
|
||||
The System Management BIOS (SMBIOS) specification addresses how
|
||||
motherboard and system vendors present management information about
|
||||
their products in a standard format by extending the BIOS interface
|
||||
on Intel architecture systems.
|
||||
|
||||
Check http://www.dmtf.org/standards/smbios for details.
|
||||
|
||||
config SMBIOS_MANUFACTURER
|
||||
string "SMBIOS Manufacturer"
|
||||
depends on GENERATE_SMBIOS_TABLE
|
||||
default SYS_VENDOR
|
||||
help
|
||||
The board manufacturer to store in SMBIOS structures.
|
||||
Change this to override the default one (CONFIG_SYS_VENDOR).
|
||||
|
||||
config SMBIOS_PRODUCT_NAME
|
||||
string "SMBIOS Product Name"
|
||||
depends on GENERATE_SMBIOS_TABLE
|
||||
default SYS_BOARD
|
||||
help
|
||||
The product name to store in SMBIOS structures.
|
||||
Change this to override the default one (CONFIG_SYS_BOARD).
|
||||
|
||||
endmenu
|
||||
|
||||
config MAX_PIRQ_LINKS
|
||||
|
@ -189,6 +189,7 @@ static const struct cpu_ops cpu_x86_baytrail_ops = {
|
||||
.get_desc = cpu_x86_get_desc,
|
||||
.get_info = baytrail_get_info,
|
||||
.get_count = baytrail_get_count,
|
||||
.get_vendor = cpu_x86_get_vendor,
|
||||
};
|
||||
|
||||
static const struct udevice_id cpu_x86_baytrail_ids[] = {
|
||||
|
@ -743,6 +743,7 @@ static const struct cpu_ops cpu_x86_broadwell_ops = {
|
||||
.get_desc = cpu_x86_get_desc,
|
||||
.get_info = broadwell_get_info,
|
||||
.get_count = broadwell_get_count,
|
||||
.get_vendor = cpu_x86_get_vendor,
|
||||
};
|
||||
|
||||
static const struct udevice_id cpu_x86_broadwell_ids[] = {
|
||||
|
@ -15,9 +15,26 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
int cpu_x86_bind(struct udevice *dev)
|
||||
{
|
||||
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
|
||||
struct cpuid_result res;
|
||||
|
||||
plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"intel,apic-id", -1);
|
||||
plat->family = gd->arch.x86;
|
||||
res = cpuid(1);
|
||||
plat->id[0] = res.eax;
|
||||
plat->id[1] = res.edx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_x86_get_vendor(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
const char *vendor = cpu_vendor_name(gd->arch.x86_vendor);
|
||||
|
||||
if (size < (strlen(vendor) + 1))
|
||||
return -ENOSPC;
|
||||
|
||||
strcpy(buf, vendor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -60,6 +77,7 @@ static int cpu_x86_get_count(struct udevice *dev)
|
||||
static const struct cpu_ops cpu_x86_ops = {
|
||||
.get_desc = cpu_x86_get_desc,
|
||||
.get_count = cpu_x86_get_count,
|
||||
.get_vendor = cpu_x86_get_vendor,
|
||||
};
|
||||
|
||||
static const struct udevice_id cpu_x86_ids[] = {
|
||||
|
@ -477,6 +477,7 @@ static const struct cpu_ops cpu_x86_model_206ax_ops = {
|
||||
.get_desc = cpu_x86_get_desc,
|
||||
.get_info = model_206ax_get_info,
|
||||
.get_count = model_206ax_get_count,
|
||||
.get_vendor = cpu_x86_get_vendor,
|
||||
};
|
||||
|
||||
static const struct udevice_id cpu_x86_model_206ax_ids[] = {
|
||||
|
@ -28,7 +28,10 @@ SECTIONS
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
|
||||
.rodata : {
|
||||
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
|
||||
KEEP(*(.rodata.efi.init));
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
.data : { *(.data*) }
|
||||
@ -40,6 +43,37 @@ SECTIONS
|
||||
.got : { *(.got*) }
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.__efi_runtime_start : {
|
||||
*(.__efi_runtime_start)
|
||||
}
|
||||
|
||||
.efi_runtime : {
|
||||
*(efi_runtime_text)
|
||||
*(efi_runtime_data)
|
||||
}
|
||||
|
||||
.__efi_runtime_stop : {
|
||||
*(.__efi_runtime_stop)
|
||||
}
|
||||
|
||||
.efi_runtime_rel_start :
|
||||
{
|
||||
*(.__efi_runtime_rel_start)
|
||||
}
|
||||
|
||||
.efi_runtime_rel : {
|
||||
*(.relefi_runtime_text)
|
||||
*(.relefi_runtime_data)
|
||||
}
|
||||
|
||||
.efi_runtime_rel_stop :
|
||||
{
|
||||
*(.__efi_runtime_rel_stop)
|
||||
}
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
__data_end = .;
|
||||
__init_end = .;
|
||||
|
||||
|
@ -31,4 +31,17 @@ int cpu_x86_bind(struct udevice *dev);
|
||||
*/
|
||||
int cpu_x86_get_desc(struct udevice *dev, char *buf, int size);
|
||||
|
||||
/**
|
||||
* cpu_x86_get_vendor() - Get a vendor string for an x86 CPU
|
||||
*
|
||||
* This uses cpu_vendor_name() and is suitable to use as the get_vendor()
|
||||
* method for the CPU uclass.
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CPU)
|
||||
* @buf: Buffer to place string
|
||||
* @size: Size of string space
|
||||
* @return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
|
||||
*/
|
||||
int cpu_x86_get_vendor(struct udevice *dev, char *buf, int size);
|
||||
|
||||
#endif /* _ASM_CPU_X86_H */
|
||||
|
@ -28,8 +28,8 @@ obj-y += pirq_routing.o
|
||||
obj-y += relocate.o
|
||||
obj-y += physmem.o
|
||||
obj-$(CONFIG_X86_RAMTEST) += ramtest.o
|
||||
obj-y += sections.o
|
||||
obj-y += sfi.o
|
||||
obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
|
||||
obj-y += string.o
|
||||
ifndef CONFIG_QEMU
|
||||
obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
|
||||
|
12
arch/x86/lib/sections.c
Normal file
12
arch/x86/lib/sections.c
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2013 Albert ARIBAUD <albert.u.boot@aribaud.net>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
char __efi_runtime_start[0] __attribute__((section(".__efi_runtime_start")));
|
||||
char __efi_runtime_stop[0] __attribute__((section(".__efi_runtime_stop")));
|
||||
char __efi_runtime_rel_start[0]
|
||||
__attribute__((section(".__efi_runtime_rel_start")));
|
||||
char __efi_runtime_rel_stop[0]
|
||||
__attribute__((section(".__efi_runtime_rel_stop")));
|
@ -5,13 +5,18 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <smbios.h>
|
||||
#include <asm/sfi.h>
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/smbios.h>
|
||||
#include <asm/tables.h>
|
||||
#include <asm/acpi_table.h>
|
||||
#include <asm/coreboot_tables.h>
|
||||
|
||||
static u32 write_smbios_table_wrapper(u32 addr)
|
||||
{
|
||||
return write_smbios_table(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function prototype to write a specific configuration table
|
||||
*
|
||||
@ -34,7 +39,7 @@ static table_write table_write_funcs[] = {
|
||||
write_acpi_tables,
|
||||
#endif
|
||||
#ifdef CONFIG_GENERATE_SMBIOS_TABLE
|
||||
write_smbios_table,
|
||||
write_smbios_table_wrapper,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -427,8 +427,3 @@ int board_usb_cleanup(int index, enum usb_init_type init)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void reset_misc(void)
|
||||
{
|
||||
psci_system_reset(true);
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <libfdt_env.h>
|
||||
#include <memalign.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm-generic/sections.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
@ -52,7 +54,7 @@ static struct efi_device_path_file_path bootefi_device_path[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static efi_status_t bootefi_open_dp(void *handle, efi_guid_t *protocol,
|
||||
static efi_status_t EFIAPI bootefi_open_dp(void *handle, efi_guid_t *protocol,
|
||||
void **protocol_interface, void *agent_handle,
|
||||
void *controller_handle, uint32_t attributes)
|
||||
{
|
||||
@ -145,7 +147,8 @@ static void *copy_fdt(void *fdt)
|
||||
*/
|
||||
static unsigned long do_bootefi_exec(void *efi, void *fdt)
|
||||
{
|
||||
ulong (*entry)(void *image_handle, struct efi_system_table *st);
|
||||
ulong (*entry)(void *image_handle, struct efi_system_table *st)
|
||||
asmlinkage;
|
||||
ulong fdt_pages, fdt_size, fdt_start, fdt_end;
|
||||
bootm_headers_t img = { 0 };
|
||||
|
||||
@ -204,7 +207,16 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt)
|
||||
|
||||
if (!memcmp(bootefi_device_path[0].str, "N\0e\0t", 6))
|
||||
loaded_image_info.device_handle = nethandle;
|
||||
else
|
||||
loaded_image_info.device_handle = bootefi_device_path;
|
||||
#endif
|
||||
#ifdef CONFIG_GENERATE_SMBIOS_TABLE
|
||||
efi_smbios_register();
|
||||
#endif
|
||||
|
||||
/* Initialize EFI runtime services */
|
||||
efi_reset_system_init();
|
||||
efi_get_time_init();
|
||||
|
||||
/* Call our payload! */
|
||||
debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
|
||||
|
@ -44,6 +44,16 @@ int cpu_get_count(struct udevice *dev)
|
||||
return ops->get_count(dev);
|
||||
}
|
||||
|
||||
int cpu_get_vendor(struct udevice *dev, char *buf, int size)
|
||||
{
|
||||
struct cpu_ops *ops = cpu_get_ops(dev);
|
||||
|
||||
if (!ops->get_vendor)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->get_vendor(dev, buf, size);
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(cpu_bus) = {
|
||||
.name = "cpu_bus",
|
||||
.id = UCLASS_SIMPLE_BUS,
|
||||
|
@ -21,6 +21,8 @@ struct cpu_platdata {
|
||||
int cpu_id;
|
||||
int ucode_version;
|
||||
ulong device_id;
|
||||
u16 family; /* DMTF CPU Family */
|
||||
u32 id[2]; /* DMTF CPU Processor IDs */
|
||||
};
|
||||
|
||||
/* CPU features - mostly just a placeholder for now */
|
||||
@ -71,6 +73,16 @@ struct cpu_ops {
|
||||
* @return CPU count if OK, -ve on error
|
||||
*/
|
||||
int (*get_count)(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* get_vendor() - Get vendor name of a CPU
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CPU)
|
||||
* @buf: Buffer to place string
|
||||
* @size: Size of string space
|
||||
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
|
||||
*/
|
||||
int (*get_vendor)(struct udevice *dev, char *buf, int size);
|
||||
};
|
||||
|
||||
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops)
|
||||
@ -102,4 +114,14 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info);
|
||||
*/
|
||||
int cpu_get_count(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* cpu_get_vendor() - Get vendor name of a CPU
|
||||
*
|
||||
* @dev: Device to check (UCLASS_CPU)
|
||||
* @buf: Buffer to place string
|
||||
* @size: Size of string space
|
||||
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
|
||||
*/
|
||||
int cpu_get_vendor(struct udevice *dev, char *buf, int size);
|
||||
|
||||
#endif
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef _EFI_H
|
||||
#define _EFI_H
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
@ -22,7 +23,7 @@
|
||||
/* EFI uses the Microsoft ABI which is not the default for GCC */
|
||||
#define EFIAPI __attribute__((ms_abi))
|
||||
#else
|
||||
#define EFIAPI
|
||||
#define EFIAPI asmlinkage
|
||||
#endif
|
||||
|
||||
struct efi_device_path;
|
||||
|
@ -201,6 +201,10 @@ struct efi_runtime_services {
|
||||
EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, \
|
||||
0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
|
||||
|
||||
#define SMBIOS_TABLE_GUID \
|
||||
EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, \
|
||||
0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
|
||||
|
||||
struct efi_configuration_table
|
||||
{
|
||||
efi_guid_t guid;
|
||||
|
@ -85,6 +85,8 @@ int efi_disk_register(void);
|
||||
int efi_gop_register(void);
|
||||
/* Called by bootefi to make the network interface available */
|
||||
int efi_net_register(void **handle);
|
||||
/* Called by bootefi to make SMBIOS tables available */
|
||||
void efi_smbios_register(void);
|
||||
|
||||
/* Called by networking code to memorize the dhcp ack package */
|
||||
void efi_net_set_dhcp_ack(void *pkt, int len);
|
||||
@ -93,7 +95,7 @@ void efi_net_set_dhcp_ack(void *pkt, int len);
|
||||
* Stub implementation for a protocol opener that just returns the handle as
|
||||
* interface
|
||||
*/
|
||||
efi_status_t efi_return_handle(void *handle,
|
||||
efi_status_t EFIAPI efi_return_handle(void *handle,
|
||||
efi_guid_t *protocol, void **protocol_interface,
|
||||
void *agent_handle, void *controller_handle,
|
||||
uint32_t attributes);
|
||||
@ -117,8 +119,13 @@ void *efi_alloc(uint64_t len, int memory_type);
|
||||
/* More specific EFI memory allocator, called by EFI payloads */
|
||||
efi_status_t efi_allocate_pages(int type, int memory_type, unsigned long pages,
|
||||
uint64_t *memory);
|
||||
/* EFI memory free function. Not implemented today */
|
||||
/* EFI memory free function. */
|
||||
efi_status_t efi_free_pages(uint64_t memory, unsigned long pages);
|
||||
/* EFI memory allocator for small allocations */
|
||||
efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
|
||||
void **buffer);
|
||||
/* EFI pool memory free function. */
|
||||
efi_status_t efi_free_pool(void *buffer);
|
||||
/* Returns the EFI memory map */
|
||||
efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
|
||||
struct efi_mem_desc *memory_map,
|
||||
@ -130,6 +137,8 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
|
||||
bool overlap_only_ram);
|
||||
/* Called by board init to initialize the EFI memory map */
|
||||
int efi_memory_init(void);
|
||||
/* Adds new or overrides configuration table entry to the system table */
|
||||
efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table);
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
|
||||
extern void *efi_bounce_buffer;
|
||||
@ -147,14 +156,32 @@ static inline void ascii2unicode(u16 *unicode, const char *ascii)
|
||||
* Use these to indicate that your code / data should go into the EFI runtime
|
||||
* section and thus still be available when the OS is running
|
||||
*/
|
||||
#define EFI_RUNTIME_DATA __attribute__ ((section ("efi_runtime_data")))
|
||||
#define EFI_RUNTIME_TEXT __attribute__ ((section ("efi_runtime_text")))
|
||||
#define __efi_runtime_data __attribute__ ((section ("efi_runtime_data")))
|
||||
#define __efi_runtime __attribute__ ((section ("efi_runtime_text")))
|
||||
|
||||
/* Call this with mmio_ptr as the _pointer_ to a pointer to an MMIO region
|
||||
* to make it available at runtime */
|
||||
void efi_add_runtime_mmio(void *mmio_ptr, u64 len);
|
||||
|
||||
/* Boards may provide the functions below to implement RTS functionality */
|
||||
|
||||
void __efi_runtime EFIAPI efi_reset_system(
|
||||
enum efi_reset_type reset_type,
|
||||
efi_status_t reset_status,
|
||||
unsigned long data_size, void *reset_data);
|
||||
void efi_reset_system_init(void);
|
||||
|
||||
efi_status_t __efi_runtime EFIAPI efi_get_time(
|
||||
struct efi_time *time,
|
||||
struct efi_time_cap *capabilities);
|
||||
void efi_get_time_init(void);
|
||||
|
||||
#else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */
|
||||
|
||||
/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */
|
||||
#define EFI_RUNTIME_DATA
|
||||
#define EFI_RUNTIME_TEXT
|
||||
#define __efi_runtime_data
|
||||
#define __efi_runtime
|
||||
static inline void efi_add_runtime_mmio(void **mmio_ptr, u64 len) { }
|
||||
|
||||
/* No loader configured, stub out EFI_ENTRY */
|
||||
static inline void efi_restore_gd(void) { }
|
||||
|
@ -55,6 +55,7 @@ struct __packed smbios_entry {
|
||||
#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT (1 << 16)
|
||||
|
||||
#define BIOS_CHARACTERISTICS_EXT1_ACPI (1 << 0)
|
||||
#define BIOS_CHARACTERISTICS_EXT1_UEFI (1 << 3)
|
||||
#define BIOS_CHARACTERISTICS_EXT2_TARGET (1 << 2)
|
||||
|
||||
struct __packed smbios_type0 {
|
||||
@ -139,6 +140,9 @@ struct __packed smbios_type3 {
|
||||
#define SMBIOS_PROCESSOR_STATUS_ENABLED 1
|
||||
#define SMBIOS_PROCESSOR_UPGRADE_NONE 6
|
||||
|
||||
#define SMBIOS_PROCESSOR_FAMILY_OTHER 1
|
||||
#define SMBIOS_PROCESSOR_FAMILY_UNKNOWN 2
|
||||
|
||||
struct __packed smbios_type4 {
|
||||
u8 type;
|
||||
u8 length;
|
||||
@ -221,7 +225,7 @@ static inline void fill_smbios_header(void *table, int type,
|
||||
* @handle: the structure's handle, a unique 16-bit number
|
||||
* @return: size of the structure
|
||||
*/
|
||||
typedef int (*smbios_write_type)(u32 *addr, int handle);
|
||||
typedef int (*smbios_write_type)(uintptr_t *addr, int handle);
|
||||
|
||||
/**
|
||||
* write_smbios_table() - Write SMBIOS table
|
||||
@ -231,6 +235,6 @@ typedef int (*smbios_write_type)(u32 *addr, int handle);
|
||||
* @addr: start address to write SMBIOS table
|
||||
* @return: end address of SMBIOS table
|
||||
*/
|
||||
u32 write_smbios_table(u32 addr);
|
||||
uintptr_t write_smbios_table(uintptr_t addr);
|
||||
|
||||
#endif /* _SMBIOS_H_ */
|
33
lib/Kconfig
33
lib/Kconfig
@ -163,6 +163,39 @@ config FDT_FIXUP_PARTITIONS
|
||||
using partition info defined in the 'mtdparts' environment
|
||||
variable.
|
||||
|
||||
menu "System tables"
|
||||
depends on (!EFI && !SYS_COREBOOT) || (ARM && EFI_LOADER)
|
||||
|
||||
config GENERATE_SMBIOS_TABLE
|
||||
bool "Generate an SMBIOS (System Management BIOS) table"
|
||||
default y
|
||||
depends on X86 || EFI_LOADER
|
||||
help
|
||||
The System Management BIOS (SMBIOS) specification addresses how
|
||||
motherboard and system vendors present management information about
|
||||
their products in a standard format by extending the BIOS interface
|
||||
on Intel architecture systems.
|
||||
|
||||
Check http://www.dmtf.org/standards/smbios for details.
|
||||
|
||||
config SMBIOS_MANUFACTURER
|
||||
string "SMBIOS Manufacturer"
|
||||
depends on GENERATE_SMBIOS_TABLE
|
||||
default SYS_VENDOR
|
||||
help
|
||||
The board manufacturer to store in SMBIOS structures.
|
||||
Change this to override the default one (CONFIG_SYS_VENDOR).
|
||||
|
||||
config SMBIOS_PRODUCT_NAME
|
||||
string "SMBIOS Product Name"
|
||||
depends on GENERATE_SMBIOS_TABLE
|
||||
default SYS_BOARD
|
||||
help
|
||||
The product name to store in SMBIOS structures.
|
||||
Change this to override the default one (CONFIG_SYS_BOARD).
|
||||
|
||||
endmenu
|
||||
|
||||
source lib/efi/Kconfig
|
||||
source lib/efi_loader/Kconfig
|
||||
|
||||
|
@ -27,6 +27,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o
|
||||
obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
|
||||
obj-$(CONFIG_GZIP) += gunzip.o
|
||||
obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
|
||||
obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
|
||||
obj-y += initcall.o
|
||||
obj-$(CONFIG_LMB) += lmb.o
|
||||
obj-y += ldiv.o
|
||||
@ -73,6 +74,7 @@ obj-y += linux_string.o
|
||||
obj-y += membuff.o
|
||||
obj-$(CONFIG_REGEX) += slre.o
|
||||
obj-y += string.o
|
||||
obj-y += tables_csum.o
|
||||
obj-y += time.o
|
||||
obj-$(CONFIG_TRACE) += trace.o
|
||||
obj-$(CONFIG_LIB_UUID) += uuid.o
|
||||
|
@ -12,3 +12,4 @@ obj-y += efi_memory.o
|
||||
obj-$(CONFIG_LCD) += efi_gop.o
|
||||
obj-$(CONFIG_PARTITIONS) += efi_disk.o
|
||||
obj-$(CONFIG_NET) += efi_net.o
|
||||
obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
|
||||
|
@ -37,8 +37,9 @@ static bool efi_is_direct_boot = true;
|
||||
* In most cases we want to pass an FDT to the payload, so reserve one slot of
|
||||
* config table space for it. The pointer gets populated by do_bootefi_exec().
|
||||
*/
|
||||
static struct efi_configuration_table EFI_RUNTIME_DATA efi_conf_table[1];
|
||||
static struct efi_configuration_table __efi_runtime_data efi_conf_table[2];
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
/*
|
||||
* The "gd" pointer lives in a register on ARM and AArch64 that we declare
|
||||
* fixed when compiling U-Boot. However, the payload does not know about that
|
||||
@ -46,16 +47,20 @@ static struct efi_configuration_table EFI_RUNTIME_DATA efi_conf_table[1];
|
||||
* EFI callback entry/exit.
|
||||
*/
|
||||
static volatile void *efi_gd, *app_gd;
|
||||
#endif
|
||||
|
||||
/* Called from do_bootefi_exec() */
|
||||
void efi_save_gd(void)
|
||||
{
|
||||
#ifdef CONFIG_ARM
|
||||
efi_gd = gd;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Called on every callback entry */
|
||||
void efi_restore_gd(void)
|
||||
{
|
||||
#ifdef CONFIG_ARM
|
||||
/* Only restore if we're already in EFI context */
|
||||
if (!efi_gd)
|
||||
return;
|
||||
@ -63,12 +68,16 @@ void efi_restore_gd(void)
|
||||
if (gd != efi_gd)
|
||||
app_gd = gd;
|
||||
gd = efi_gd;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Called on every callback exit */
|
||||
efi_status_t efi_exit_func(efi_status_t ret)
|
||||
{
|
||||
#ifdef CONFIG_ARM
|
||||
gd = app_gd;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -130,22 +139,23 @@ efi_status_t EFIAPI efi_get_memory_map_ext(unsigned long *memory_map_size,
|
||||
return EFI_EXIT(r);
|
||||
}
|
||||
|
||||
static efi_status_t EFIAPI efi_allocate_pool(int pool_type, unsigned long size,
|
||||
void **buffer)
|
||||
static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type,
|
||||
unsigned long size,
|
||||
void **buffer)
|
||||
{
|
||||
efi_status_t r;
|
||||
|
||||
EFI_ENTRY("%d, %ld, %p", pool_type, size, buffer);
|
||||
r = efi_allocate_pages(0, pool_type, (size + 0xfff) >> 12, (void*)buffer);
|
||||
r = efi_allocate_pool(pool_type, size, buffer);
|
||||
return EFI_EXIT(r);
|
||||
}
|
||||
|
||||
static efi_status_t EFIAPI efi_free_pool(void *buffer)
|
||||
static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
|
||||
{
|
||||
efi_status_t r;
|
||||
|
||||
EFI_ENTRY("%p", buffer);
|
||||
r = efi_free_pages((ulong)buffer, 0);
|
||||
r = efi_free_pool(buffer);
|
||||
return EFI_EXIT(r);
|
||||
}
|
||||
|
||||
@ -159,7 +169,7 @@ static struct {
|
||||
u32 trigger_time;
|
||||
u64 trigger_next;
|
||||
unsigned long notify_tpl;
|
||||
void (*notify_function) (void *event, void *context);
|
||||
void (EFIAPI *notify_function) (void *event, void *context);
|
||||
void *notify_context;
|
||||
} efi_event = {
|
||||
/* Disable timers on bootup */
|
||||
@ -168,7 +178,8 @@ static struct {
|
||||
|
||||
static efi_status_t EFIAPI efi_create_event(
|
||||
enum efi_event_type type, ulong notify_tpl,
|
||||
void (*notify_function) (void *event, void *context),
|
||||
void (EFIAPI *notify_function) (void *event,
|
||||
void *context),
|
||||
void *notify_context, void **event)
|
||||
{
|
||||
EFI_ENTRY("%d, 0x%lx, %p, %p", type, notify_tpl, notify_function,
|
||||
@ -375,31 +386,35 @@ static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol,
|
||||
return EFI_EXIT(EFI_NOT_FOUND);
|
||||
}
|
||||
|
||||
static efi_status_t EFIAPI efi_install_configuration_table(efi_guid_t *guid,
|
||||
void *table)
|
||||
efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table)
|
||||
{
|
||||
int i;
|
||||
|
||||
EFI_ENTRY("%p, %p", guid, table);
|
||||
|
||||
/* Check for guid override */
|
||||
for (i = 0; i < systab.nr_tables; i++) {
|
||||
if (!guidcmp(guid, &efi_conf_table[i].guid)) {
|
||||
efi_conf_table[i].table = table;
|
||||
return EFI_EXIT(EFI_SUCCESS);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* No override, check for overflow */
|
||||
if (i >= ARRAY_SIZE(efi_conf_table))
|
||||
return EFI_EXIT(EFI_OUT_OF_RESOURCES);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
/* Add a new entry */
|
||||
memcpy(&efi_conf_table[i].guid, guid, sizeof(*guid));
|
||||
efi_conf_table[i].table = table;
|
||||
systab.nr_tables = i;
|
||||
systab.nr_tables = i + 1;
|
||||
|
||||
return EFI_EXIT(EFI_SUCCESS);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
|
||||
void *table)
|
||||
{
|
||||
EFI_ENTRY("%p, %p", guid, table);
|
||||
return EFI_EXIT(efi_install_configuration_table(guid, table));
|
||||
}
|
||||
|
||||
static efi_status_t EFIAPI efi_load_image(bool boot_policy,
|
||||
@ -734,8 +749,8 @@ static const struct efi_boot_services efi_boot_services = {
|
||||
.allocate_pages = efi_allocate_pages_ext,
|
||||
.free_pages = efi_free_pages_ext,
|
||||
.get_memory_map = efi_get_memory_map_ext,
|
||||
.allocate_pool = efi_allocate_pool,
|
||||
.free_pool = efi_free_pool,
|
||||
.allocate_pool = efi_allocate_pool_ext,
|
||||
.free_pool = efi_free_pool_ext,
|
||||
.create_event = efi_create_event,
|
||||
.set_timer = efi_set_timer,
|
||||
.wait_for_event = efi_wait_for_event,
|
||||
@ -750,7 +765,7 @@ static const struct efi_boot_services efi_boot_services = {
|
||||
.register_protocol_notify = efi_register_protocol_notify,
|
||||
.locate_handle = efi_locate_handle,
|
||||
.locate_device_path = efi_locate_device_path,
|
||||
.install_configuration_table = efi_install_configuration_table,
|
||||
.install_configuration_table = efi_install_configuration_table_ext,
|
||||
.load_image = efi_load_image,
|
||||
.start_image = efi_start_image,
|
||||
.exit = efi_exit,
|
||||
@ -775,10 +790,10 @@ static const struct efi_boot_services efi_boot_services = {
|
||||
};
|
||||
|
||||
|
||||
static uint16_t EFI_RUNTIME_DATA firmware_vendor[] =
|
||||
static uint16_t __efi_runtime_data firmware_vendor[] =
|
||||
{ 'D','a','s',' ','U','-','b','o','o','t',0 };
|
||||
|
||||
struct efi_system_table EFI_RUNTIME_DATA systab = {
|
||||
struct efi_system_table __efi_runtime_data systab = {
|
||||
.hdr = {
|
||||
.signature = EFI_SYSTEM_TABLE_SIGNATURE,
|
||||
.revision = 0x20005, /* 2.5 */
|
||||
|
@ -35,9 +35,10 @@ struct efi_disk_obj {
|
||||
const struct blk_desc *desc;
|
||||
};
|
||||
|
||||
static efi_status_t efi_disk_open_block(void *handle, efi_guid_t *protocol,
|
||||
void **protocol_interface, void *agent_handle,
|
||||
void *controller_handle, uint32_t attributes)
|
||||
static efi_status_t EFIAPI efi_disk_open_block(void *handle,
|
||||
efi_guid_t *protocol, void **protocol_interface,
|
||||
void *agent_handle, void *controller_handle,
|
||||
uint32_t attributes)
|
||||
{
|
||||
struct efi_disk_obj *diskobj = handle;
|
||||
|
||||
@ -46,7 +47,7 @@ static efi_status_t efi_disk_open_block(void *handle, efi_guid_t *protocol,
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static efi_status_t efi_disk_open_dp(void *handle, efi_guid_t *protocol,
|
||||
static efi_status_t EFIAPI efi_disk_open_dp(void *handle, efi_guid_t *protocol,
|
||||
void **protocol_interface, void *agent_handle,
|
||||
void *controller_handle, uint32_t attributes)
|
||||
{
|
||||
@ -108,7 +109,7 @@ static efi_status_t EFIAPI efi_disk_rw_blocks(struct efi_block_io *this,
|
||||
return EFI_EXIT(EFI_SUCCESS);
|
||||
}
|
||||
|
||||
static efi_status_t efi_disk_read_blocks(struct efi_block_io *this,
|
||||
static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
|
||||
u32 media_id, u64 lba, unsigned long buffer_size,
|
||||
void *buffer)
|
||||
{
|
||||
@ -143,7 +144,7 @@ static efi_status_t efi_disk_read_blocks(struct efi_block_io *this,
|
||||
return EFI_EXIT(r);
|
||||
}
|
||||
|
||||
static efi_status_t efi_disk_write_blocks(struct efi_block_io *this,
|
||||
static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
|
||||
u32 media_id, u64 lba, unsigned long buffer_size,
|
||||
void *buffer)
|
||||
{
|
||||
|
@ -129,6 +129,7 @@ int efi_gop_register(void)
|
||||
{
|
||||
struct efi_gop_obj *gopobj;
|
||||
u32 bpix, col, row;
|
||||
u64 fb_base, fb_size;
|
||||
|
||||
#ifdef CONFIG_DM_VIDEO
|
||||
struct udevice *vdev;
|
||||
@ -141,11 +142,16 @@ int efi_gop_register(void)
|
||||
bpix = priv->bpix;
|
||||
col = video_get_xsize(vdev);
|
||||
row = video_get_ysize(vdev);
|
||||
fb_base = (uintptr_t)priv->fb;
|
||||
fb_size = priv->fb_size;
|
||||
#else
|
||||
int line_len;
|
||||
|
||||
bpix = panel_info.vl_bpix;
|
||||
col = panel_info.vl_col;
|
||||
row = panel_info.vl_row;
|
||||
fb_base = gd->fb_base;
|
||||
fb_size = lcd_get_size(&line_len);
|
||||
#endif
|
||||
|
||||
switch (bpix) {
|
||||
@ -177,6 +183,16 @@ int efi_gop_register(void)
|
||||
gopobj->mode.info = &gopobj->info;
|
||||
gopobj->mode.info_size = sizeof(gopobj->info);
|
||||
|
||||
#ifdef CONFIG_DM_VIDEO
|
||||
if (bpix == VIDEO_BPP32) {
|
||||
#else
|
||||
if (bpix == LCD_COLOR32) {
|
||||
#endif
|
||||
/* With 32bit color space we can directly expose the fb */
|
||||
gopobj->mode.fb_base = fb_base;
|
||||
gopobj->mode.fb_size = fb_size;
|
||||
}
|
||||
|
||||
gopobj->info.version = 0;
|
||||
gopobj->info.width = col;
|
||||
gopobj->info.height = row;
|
||||
|
@ -33,6 +33,19 @@ LIST_HEAD(efi_mem);
|
||||
void *efi_bounce_buffer;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* U-Boot services each EFI AllocatePool request as a separate
|
||||
* (multiple) page allocation. We have to track the number of pages
|
||||
* to be able to free the correct amount later.
|
||||
* EFI requires 8 byte alignment for pool allocations, so we can
|
||||
* prepend each allocation with an 64 bit header tracking the
|
||||
* allocation size, and hand out the remainder to the caller.
|
||||
*/
|
||||
struct efi_pool_allocation {
|
||||
u64 num_pages;
|
||||
char data[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Sorts the memory list from highest address to lowest address
|
||||
*
|
||||
@ -62,9 +75,17 @@ static void efi_mem_sort(void)
|
||||
* Unmaps all memory occupied by the carve_desc region from the
|
||||
* list entry pointed to by map.
|
||||
*
|
||||
* Returns 1 if carving was performed or 0 if the regions don't overlap.
|
||||
* Returns -1 if it would affect non-RAM regions but overlap_only_ram is set.
|
||||
* Carving is only guaranteed to complete when all regions return 0.
|
||||
* Returns EFI_CARVE_NO_OVERLAP if the regions don't overlap.
|
||||
* Returns EFI_CARVE_OVERLAPS_NONRAM if the carve and map overlap,
|
||||
* and the map contains anything but free ram.
|
||||
* (only when overlap_only_ram is true)
|
||||
* Returns EFI_CARVE_LOOP_AGAIN if the mapping list should be traversed
|
||||
* again, as it has been altered
|
||||
* Returns the number of overlapping pages. The pages are removed from
|
||||
* the mapping list.
|
||||
*
|
||||
* In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility
|
||||
* to readd the already carved out pages to the mapping.
|
||||
*/
|
||||
static int efi_mem_carve_out(struct efi_mem_list *map,
|
||||
struct efi_mem_desc *carve_desc,
|
||||
@ -95,10 +116,13 @@ static int efi_mem_carve_out(struct efi_mem_list *map,
|
||||
if (map_end == carve_end) {
|
||||
/* Full overlap, just remove map */
|
||||
list_del(&map->link);
|
||||
free(map);
|
||||
} else {
|
||||
map->desc.physical_start = carve_end;
|
||||
map->desc.num_pages = (map_end - carve_end)
|
||||
>> EFI_PAGE_SHIFT;
|
||||
}
|
||||
|
||||
map_desc->physical_start = carve_end;
|
||||
map_desc->num_pages = (map_end - carve_end) >> EFI_PAGE_SHIFT;
|
||||
return (carve_end - carve_start) >> EFI_PAGE_SHIFT;
|
||||
}
|
||||
|
||||
@ -114,7 +138,8 @@ static int efi_mem_carve_out(struct efi_mem_list *map,
|
||||
newmap->desc = map->desc;
|
||||
newmap->desc.physical_start = carve_start;
|
||||
newmap->desc.num_pages = (map_end - carve_start) >> EFI_PAGE_SHIFT;
|
||||
list_add_tail(&newmap->link, &efi_mem);
|
||||
/* Insert before current entry (descending address order) */
|
||||
list_add_tail(&newmap->link, &map->link);
|
||||
|
||||
/* Shrink the map to [ map_start ... carve_start ] */
|
||||
map_desc->num_pages = (carve_start - map_start) >> EFI_PAGE_SHIFT;
|
||||
@ -315,8 +340,52 @@ void *efi_alloc(uint64_t len, int memory_type)
|
||||
|
||||
efi_status_t efi_free_pages(uint64_t memory, unsigned long pages)
|
||||
{
|
||||
/* We don't free, let's cross our fingers we have plenty RAM */
|
||||
return EFI_SUCCESS;
|
||||
uint64_t r = 0;
|
||||
|
||||
r = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
|
||||
/* Merging of adjacent free regions is missing */
|
||||
|
||||
if (r == memory)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
|
||||
void **buffer)
|
||||
{
|
||||
efi_status_t r;
|
||||
efi_physical_addr_t t;
|
||||
u64 num_pages = (size + sizeof(u64) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
||||
|
||||
if (size == 0) {
|
||||
*buffer = NULL;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
r = efi_allocate_pages(0, pool_type, num_pages, &t);
|
||||
|
||||
if (r == EFI_SUCCESS) {
|
||||
struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
|
||||
alloc->num_pages = num_pages;
|
||||
*buffer = alloc->data;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
efi_status_t efi_free_pool(void *buffer)
|
||||
{
|
||||
efi_status_t r;
|
||||
struct efi_pool_allocation *alloc;
|
||||
|
||||
alloc = container_of(buffer, struct efi_pool_allocation, data);
|
||||
/* Sanity check, was the supplied address returned by allocate_pool */
|
||||
assert(((uintptr_t)alloc & EFI_PAGE_MASK) == 0);
|
||||
|
||||
r = efi_free_pages((uintptr_t)alloc, alloc->num_pages);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
|
||||
@ -328,6 +397,7 @@ efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
|
||||
ulong map_size = 0;
|
||||
int map_entries = 0;
|
||||
struct list_head *lhandle;
|
||||
unsigned long provided_map_size = *memory_map_size;
|
||||
|
||||
list_for_each(lhandle, &efi_mem)
|
||||
map_entries++;
|
||||
@ -342,7 +412,7 @@ efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
|
||||
if (descriptor_version)
|
||||
*descriptor_version = EFI_MEMORY_DESCRIPTOR_VERSION;
|
||||
|
||||
if (*memory_map_size < map_size)
|
||||
if (provided_map_size < map_size)
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
|
||||
/* Copy list into array */
|
||||
|
@ -152,7 +152,14 @@ static efi_status_t EFIAPI efi_net_transmit(struct efi_simple_network *this,
|
||||
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
|
||||
/* Ethernet packets always fit, just bounce */
|
||||
memcpy(efi_bounce_buffer, buffer, buffer_size);
|
||||
net_send_packet(efi_bounce_buffer, buffer_size);
|
||||
#else
|
||||
net_send_packet(buffer, buffer_size);
|
||||
#endif
|
||||
|
||||
new_tx_packet = buffer;
|
||||
|
||||
return EFI_EXIT(EFI_SUCCESS);
|
||||
@ -191,7 +198,7 @@ static efi_status_t EFIAPI efi_net_receive(struct efi_simple_network *this,
|
||||
return EFI_EXIT(EFI_SUCCESS);
|
||||
}
|
||||
|
||||
static efi_status_t efi_net_open_dp(void *handle, efi_guid_t *protocol,
|
||||
static efi_status_t EFIAPI efi_net_open_dp(void *handle, efi_guid_t *protocol,
|
||||
void **protocol_interface, void *agent_handle,
|
||||
void *controller_handle, uint32_t attributes)
|
||||
{
|
||||
@ -203,7 +210,7 @@ static efi_status_t efi_net_open_dp(void *handle, efi_guid_t *protocol,
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static efi_status_t efi_net_open_pxe(void *handle, efi_guid_t *protocol,
|
||||
static efi_status_t EFIAPI efi_net_open_pxe(void *handle, efi_guid_t *protocol,
|
||||
void **protocol_interface, void *agent_handle,
|
||||
void *controller_handle, uint32_t attributes)
|
||||
{
|
||||
|
@ -16,9 +16,19 @@
|
||||
/* For manual relocation support */
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_unimplemented(void);
|
||||
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_device_error(void);
|
||||
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_invalid_parameter(void);
|
||||
struct efi_runtime_mmio_list {
|
||||
struct list_head link;
|
||||
void **ptr;
|
||||
u64 paddr;
|
||||
u64 len;
|
||||
};
|
||||
|
||||
/* This list contains all runtime available mmio regions */
|
||||
LIST_HEAD(efi_runtime_mmio);
|
||||
|
||||
static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void);
|
||||
static efi_status_t __efi_runtime EFIAPI efi_device_error(void);
|
||||
static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void);
|
||||
|
||||
#ifdef CONFIG_SYS_CACHELINE_SIZE
|
||||
#define EFI_CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE
|
||||
@ -34,6 +44,10 @@ static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_invalid_parameter(void);
|
||||
#elif defined(CONFIG_ARM)
|
||||
#define R_RELATIVE 23
|
||||
#define R_MASK 0xffULL
|
||||
#elif defined(CONFIG_X86)
|
||||
#include <asm/elf.h>
|
||||
#define R_RELATIVE R_386_RELATIVE
|
||||
#define R_MASK 0xffULL
|
||||
#else
|
||||
#error Need to add relocation awareness
|
||||
#endif
|
||||
@ -55,9 +69,10 @@ struct elf_rela {
|
||||
* handle a good number of runtime callbacks
|
||||
*/
|
||||
|
||||
static void EFIAPI efi_reset_system(enum efi_reset_type reset_type,
|
||||
efi_status_t reset_status,
|
||||
unsigned long data_size, void *reset_data)
|
||||
static void EFIAPI efi_reset_system_boottime(
|
||||
enum efi_reset_type reset_type,
|
||||
efi_status_t reset_status,
|
||||
unsigned long data_size, void *reset_data)
|
||||
{
|
||||
EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size,
|
||||
reset_data);
|
||||
@ -72,11 +87,12 @@ static void EFIAPI efi_reset_system(enum efi_reset_type reset_type,
|
||||
break;
|
||||
}
|
||||
|
||||
EFI_EXIT(EFI_SUCCESS);
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
static efi_status_t EFIAPI efi_get_time(struct efi_time *time,
|
||||
struct efi_time_cap *capabilities)
|
||||
static efi_status_t EFIAPI efi_get_time_boottime(
|
||||
struct efi_time *time,
|
||||
struct efi_time_cap *capabilities)
|
||||
{
|
||||
#if defined(CONFIG_CMD_DATE) && defined(CONFIG_DM_RTC)
|
||||
struct rtc_time tm;
|
||||
@ -107,6 +123,33 @@ static efi_status_t EFIAPI efi_get_time(struct efi_time *time,
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Boards may override the helpers below to implement RTS functionality */
|
||||
|
||||
void __weak __efi_runtime EFIAPI efi_reset_system(
|
||||
enum efi_reset_type reset_type,
|
||||
efi_status_t reset_status,
|
||||
unsigned long data_size, void *reset_data)
|
||||
{
|
||||
/* Nothing we can do */
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
void __weak efi_reset_system_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
|
||||
struct efi_time *time,
|
||||
struct efi_time_cap *capabilities)
|
||||
{
|
||||
/* Nothing we can do */
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
void __weak efi_get_time_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct efi_runtime_detach_list_struct {
|
||||
void *ptr;
|
||||
void *patchto;
|
||||
@ -116,7 +159,7 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
|
||||
{
|
||||
/* do_reset is gone */
|
||||
.ptr = &efi_runtime_services.reset_system,
|
||||
.patchto = NULL,
|
||||
.patchto = efi_reset_system,
|
||||
}, {
|
||||
/* invalidate_*cache_all are gone */
|
||||
.ptr = &efi_runtime_services.set_virtual_address_map,
|
||||
@ -124,7 +167,7 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
|
||||
}, {
|
||||
/* RTC accessors are gone */
|
||||
.ptr = &efi_runtime_services.get_time,
|
||||
.patchto = &efi_device_error,
|
||||
.patchto = &efi_get_time,
|
||||
}, {
|
||||
/* Clean up system table */
|
||||
.ptr = &systab.con_in,
|
||||
@ -233,12 +276,39 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
|
||||
EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size,
|
||||
descriptor_version, virtmap);
|
||||
|
||||
/* Rebind mmio pointers */
|
||||
for (i = 0; i < n; i++) {
|
||||
struct efi_mem_desc *map = (void*)virtmap +
|
||||
(descriptor_size * i);
|
||||
struct list_head *lhandle;
|
||||
efi_physical_addr_t map_start = map->physical_start;
|
||||
efi_physical_addr_t map_len = map->num_pages << EFI_PAGE_SHIFT;
|
||||
efi_physical_addr_t map_end = map_start + map_len;
|
||||
|
||||
/* Adjust all mmio pointers in this region */
|
||||
list_for_each(lhandle, &efi_runtime_mmio) {
|
||||
struct efi_runtime_mmio_list *lmmio;
|
||||
|
||||
lmmio = list_entry(lhandle,
|
||||
struct efi_runtime_mmio_list,
|
||||
link);
|
||||
if ((map_start <= lmmio->paddr) &&
|
||||
(map_end >= lmmio->paddr)) {
|
||||
u64 off = map->virtual_start - map_start;
|
||||
uintptr_t new_addr = lmmio->paddr + off;
|
||||
*lmmio->ptr = (void *)new_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Move the actual runtime code over */
|
||||
for (i = 0; i < n; i++) {
|
||||
struct efi_mem_desc *map;
|
||||
|
||||
map = (void*)virtmap + (descriptor_size * i);
|
||||
if (map->type == EFI_RUNTIME_SERVICES_CODE) {
|
||||
ulong new_offset = map->virtual_start - (runtime_start - gd->relocaddr);
|
||||
ulong new_offset = map->virtual_start -
|
||||
(runtime_start - gd->relocaddr);
|
||||
|
||||
efi_runtime_relocate(new_offset, map);
|
||||
/* Once we're virtual, we can no longer handle
|
||||
@ -251,6 +321,20 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
|
||||
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
void efi_add_runtime_mmio(void *mmio_ptr, u64 len)
|
||||
{
|
||||
struct efi_runtime_mmio_list *newmmio;
|
||||
|
||||
u64 pages = (len + EFI_PAGE_SIZE - 1) >> EFI_PAGE_SHIFT;
|
||||
efi_add_memory_map(*(uintptr_t *)mmio_ptr, pages, EFI_MMAP_IO, false);
|
||||
|
||||
newmmio = calloc(1, sizeof(*newmmio));
|
||||
newmmio->ptr = mmio_ptr;
|
||||
newmmio->paddr = *(uintptr_t *)mmio_ptr;
|
||||
newmmio->len = len;
|
||||
list_add_tail(&newmmio->link, &efi_runtime_mmio);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the second stage, U-Boot has disappeared. To isolate our runtime code
|
||||
* that at this point still exists from the rest, we put it into a special
|
||||
@ -262,7 +346,7 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
|
||||
* function or variable below this line.
|
||||
*
|
||||
* Please keep everything fully self-contained and annotated with
|
||||
* EFI_RUNTIME_TEXT and EFI_RUNTIME_DATA markers.
|
||||
* __efi_runtime and __efi_runtime_data markers.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -271,28 +355,28 @@ static efi_status_t EFIAPI efi_set_virtual_address_map(
|
||||
* address map calls.
|
||||
*/
|
||||
|
||||
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_unimplemented(void)
|
||||
static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_device_error(void)
|
||||
static efi_status_t __efi_runtime EFIAPI efi_device_error(void)
|
||||
{
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
static efi_status_t EFI_RUNTIME_TEXT EFIAPI efi_invalid_parameter(void)
|
||||
static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void)
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
struct efi_runtime_services EFI_RUNTIME_DATA efi_runtime_services = {
|
||||
struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
|
||||
.hdr = {
|
||||
.signature = EFI_RUNTIME_SERVICES_SIGNATURE,
|
||||
.revision = EFI_RUNTIME_SERVICES_REVISION,
|
||||
.headersize = sizeof(struct efi_table_hdr),
|
||||
},
|
||||
.get_time = &efi_get_time,
|
||||
.get_time = &efi_get_time_boottime,
|
||||
.set_time = (void *)&efi_device_error,
|
||||
.get_wakeup_time = (void *)&efi_unimplemented,
|
||||
.set_wakeup_time = (void *)&efi_unimplemented,
|
||||
@ -302,5 +386,5 @@ struct efi_runtime_services EFI_RUNTIME_DATA efi_runtime_services = {
|
||||
.get_next_variable = (void *)&efi_device_error,
|
||||
.set_variable = (void *)&efi_device_error,
|
||||
.get_next_high_mono_count = (void *)&efi_device_error,
|
||||
.reset_system = &efi_reset_system,
|
||||
.reset_system = &efi_reset_system_boottime,
|
||||
};
|
||||
|
32
lib/efi_loader/efi_smbios.c
Normal file
32
lib/efi_loader/efi_smbios.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* EFI application tables support
|
||||
*
|
||||
* Copyright (c) 2016 Alexander Graf
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <efi_loader.h>
|
||||
#include <inttypes.h>
|
||||
#include <smbios.h>
|
||||
|
||||
static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
|
||||
|
||||
void efi_smbios_register(void)
|
||||
{
|
||||
/* Map within the low 32 bits, to allow for 32bit SMBIOS tables */
|
||||
uint64_t dmi = 0xffffffff;
|
||||
/* Reserve 4kb for SMBIOS */
|
||||
uint64_t pages = 1;
|
||||
int memtype = EFI_RUNTIME_SERVICES_DATA;
|
||||
|
||||
if (efi_allocate_pages(1, memtype, pages, &dmi) != EFI_SUCCESS)
|
||||
return;
|
||||
|
||||
/* Generate SMBIOS tables */
|
||||
write_smbios_table(dmi);
|
||||
|
||||
/* And expose them to our EFI payload */
|
||||
efi_install_configuration_table(&smbios_guid, (void*)(uintptr_t)dmi);
|
||||
}
|
@ -7,10 +7,14 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <smbios.h>
|
||||
#include <tables_csum.h>
|
||||
#include <version.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/smbios.h>
|
||||
#include <asm/tables.h>
|
||||
#ifdef CONFIG_CPU
|
||||
#include <cpu.h>
|
||||
#include <dm.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#endif
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
@ -69,7 +73,7 @@ static int smbios_string_table_len(char *start)
|
||||
return len + 1;
|
||||
}
|
||||
|
||||
static int smbios_write_type0(u32 *current, int handle)
|
||||
static int smbios_write_type0(uintptr_t *current, int handle)
|
||||
{
|
||||
struct smbios_type0 *t = (struct smbios_type0 *)*current;
|
||||
int len = sizeof(struct smbios_type0);
|
||||
@ -79,14 +83,20 @@ static int smbios_write_type0(u32 *current, int handle)
|
||||
t->vendor = smbios_add_string(t->eos, "U-Boot");
|
||||
t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
|
||||
t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
|
||||
#ifdef CONFIG_ROM_SIZE
|
||||
t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
|
||||
#endif
|
||||
t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
|
||||
BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
|
||||
BIOS_CHARACTERISTICS_UPGRADEABLE;
|
||||
#ifdef CONFIG_GENERATE_ACPI_TABLE
|
||||
t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
|
||||
#endif
|
||||
#ifdef CONFIG_EFI_LOADER
|
||||
t->bios_characteristics_ext1 |= BIOS_CHARACTERISTICS_EXT1_UEFI;
|
||||
#endif
|
||||
t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
|
||||
|
||||
t->bios_major_release = 0xff;
|
||||
t->bios_minor_release = 0xff;
|
||||
t->ec_major_release = 0xff;
|
||||
@ -98,15 +108,20 @@ static int smbios_write_type0(u32 *current, int handle)
|
||||
return len;
|
||||
}
|
||||
|
||||
static int smbios_write_type1(u32 *current, int handle)
|
||||
static int smbios_write_type1(uintptr_t *current, int handle)
|
||||
{
|
||||
struct smbios_type1 *t = (struct smbios_type1 *)*current;
|
||||
int len = sizeof(struct smbios_type1);
|
||||
char *serial_str = getenv("serial#");
|
||||
|
||||
memset(t, 0, sizeof(struct smbios_type1));
|
||||
fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
|
||||
t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
|
||||
t->product_name = smbios_add_string(t->eos, CONFIG_SMBIOS_PRODUCT_NAME);
|
||||
if (serial_str) {
|
||||
strncpy((char*)t->uuid, serial_str, sizeof(t->uuid));
|
||||
t->serial_number = smbios_add_string(t->eos, serial_str);
|
||||
}
|
||||
|
||||
len = t->length + smbios_string_table_len(t->eos);
|
||||
*current += len;
|
||||
@ -114,7 +129,7 @@ static int smbios_write_type1(u32 *current, int handle)
|
||||
return len;
|
||||
}
|
||||
|
||||
static int smbios_write_type2(u32 *current, int handle)
|
||||
static int smbios_write_type2(uintptr_t *current, int handle)
|
||||
{
|
||||
struct smbios_type2 *t = (struct smbios_type2 *)*current;
|
||||
int len = sizeof(struct smbios_type2);
|
||||
@ -132,7 +147,7 @@ static int smbios_write_type2(u32 *current, int handle)
|
||||
return len;
|
||||
}
|
||||
|
||||
static int smbios_write_type3(u32 *current, int handle)
|
||||
static int smbios_write_type3(uintptr_t *current, int handle)
|
||||
{
|
||||
struct smbios_type3 *t = (struct smbios_type3 *)*current;
|
||||
int len = sizeof(struct smbios_type3);
|
||||
@ -152,26 +167,47 @@ static int smbios_write_type3(u32 *current, int handle)
|
||||
return len;
|
||||
}
|
||||
|
||||
static int smbios_write_type4(u32 *current, int handle)
|
||||
static void smbios_write_type4_dm(struct smbios_type4 *t)
|
||||
{
|
||||
u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN;
|
||||
const char *vendor = "Unknown";
|
||||
const char *name = "Unknown";
|
||||
|
||||
#ifdef CONFIG_CPU
|
||||
char processor_name[49];
|
||||
char vendor_name[49];
|
||||
struct udevice *dev = NULL;
|
||||
|
||||
uclass_find_first_device(UCLASS_CPU, &dev);
|
||||
if (dev) {
|
||||
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
|
||||
|
||||
if (plat->family)
|
||||
processor_family = plat->family;
|
||||
t->processor_id[0] = plat->id[0];
|
||||
t->processor_id[1] = plat->id[1];
|
||||
|
||||
if (!cpu_get_vendor(dev, vendor_name, sizeof(vendor_name)))
|
||||
vendor = vendor_name;
|
||||
if (!cpu_get_desc(dev, processor_name, sizeof(processor_name)))
|
||||
name = processor_name;
|
||||
}
|
||||
#endif
|
||||
|
||||
t->processor_family = processor_family;
|
||||
t->processor_manufacturer = smbios_add_string(t->eos, vendor);
|
||||
t->processor_version = smbios_add_string(t->eos, name);
|
||||
}
|
||||
|
||||
static int smbios_write_type4(uintptr_t *current, int handle)
|
||||
{
|
||||
struct smbios_type4 *t = (struct smbios_type4 *)*current;
|
||||
int len = sizeof(struct smbios_type4);
|
||||
const char *vendor;
|
||||
char *name;
|
||||
char processor_name[CPU_MAX_NAME_LEN];
|
||||
struct cpuid_result res;
|
||||
|
||||
memset(t, 0, sizeof(struct smbios_type4));
|
||||
fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
|
||||
t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
|
||||
t->processor_family = gd->arch.x86;
|
||||
vendor = cpu_vendor_name(gd->arch.x86_vendor);
|
||||
t->processor_manufacturer = smbios_add_string(t->eos, vendor);
|
||||
res = cpuid(1);
|
||||
t->processor_id[0] = res.eax;
|
||||
t->processor_id[1] = res.edx;
|
||||
name = cpu_get_name(processor_name);
|
||||
t->processor_version = smbios_add_string(t->eos, name);
|
||||
smbios_write_type4_dm(t);
|
||||
t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
|
||||
t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
|
||||
t->l1_cache_handle = 0xffff;
|
||||
@ -185,7 +221,7 @@ static int smbios_write_type4(u32 *current, int handle)
|
||||
return len;
|
||||
}
|
||||
|
||||
static int smbios_write_type32(u32 *current, int handle)
|
||||
static int smbios_write_type32(uintptr_t *current, int handle)
|
||||
{
|
||||
struct smbios_type32 *t = (struct smbios_type32 *)*current;
|
||||
int len = sizeof(struct smbios_type32);
|
||||
@ -198,7 +234,7 @@ static int smbios_write_type32(u32 *current, int handle)
|
||||
return len;
|
||||
}
|
||||
|
||||
static int smbios_write_type127(u32 *current, int handle)
|
||||
static int smbios_write_type127(uintptr_t *current, int handle)
|
||||
{
|
||||
struct smbios_type127 *t = (struct smbios_type127 *)*current;
|
||||
int len = sizeof(struct smbios_type127);
|
||||
@ -221,7 +257,7 @@ static smbios_write_type smbios_write_funcs[] = {
|
||||
smbios_write_type127
|
||||
};
|
||||
|
||||
u32 write_smbios_table(u32 addr)
|
||||
uintptr_t write_smbios_table(uintptr_t addr)
|
||||
{
|
||||
struct smbios_entry *se;
|
||||
u32 tables;
|
20
lib/tables_csum.c
Normal file
20
lib/tables_csum.c
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
u8 table_compute_checksum(void *v, int len)
|
||||
{
|
||||
u8 *bytes = v;
|
||||
u8 checksum = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
checksum -= bytes[i];
|
||||
|
||||
return checksum;
|
||||
}
|
Loading…
Reference in New Issue
Block a user