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
master
Tom Rini 8 years ago
commit 3431b392ad
  1. 18
      arch/arm/cpu/armv8/Kconfig
  2. 59
      arch/arm/cpu/armv8/fwcall.c
  3. 12
      arch/arm/include/asm/system.h
  4. 2
      arch/arm/mach-meson/board.c
  5. 0
      arch/avr32/include/asm/linkage.h
  6. 0
      arch/m68k/include/asm/linkage.h
  7. 0
      arch/microblaze/include/asm/linkage.h
  8. 0
      arch/mips/include/asm/linkage.h
  9. 0
      arch/nios2/include/asm/linkage.h
  10. 0
      arch/openrisc/include/asm/linkage.h
  11. 0
      arch/sandbox/include/asm/linkage.h
  12. 0
      arch/sh/include/asm/linkage.h
  13. 0
      arch/sparc/include/asm/linkage.h
  14. 27
      arch/x86/Kconfig
  15. 1
      arch/x86/cpu/baytrail/cpu.c
  16. 1
      arch/x86/cpu/broadwell/cpu.c
  17. 18
      arch/x86/cpu/cpu_x86.c
  18. 1
      arch/x86/cpu/ivybridge/model_206ax.c
  19. 36
      arch/x86/cpu/u-boot.lds
  20. 13
      arch/x86/include/asm/cpu_x86.h
  21. 2
      arch/x86/lib/Makefile
  22. 12
      arch/x86/lib/sections.c
  23. 9
      arch/x86/lib/tables.c
  24. 5
      board/xilinx/zynqmp/zynqmp.c
  25. 16
      cmd/bootefi.c
  26. 10
      drivers/cpu/cpu-uclass.c
  27. 22
      include/cpu.h
  28. 3
      include/efi.h
  29. 4
      include/efi_api.h
  30. 39
      include/efi_loader.h
  31. 8
      include/smbios.h
  32. 33
      lib/Kconfig
  33. 2
      lib/Makefile
  34. 1
      lib/efi_loader/Makefile
  35. 57
      lib/efi_loader/efi_boottime.c
  36. 13
      lib/efi_loader/efi_disk.c
  37. 16
      lib/efi_loader/efi_gop.c
  38. 88
      lib/efi_loader/efi_memory.c
  39. 11
      lib/efi_loader/efi_net.c
  40. 122
      lib/efi_loader/efi_runtime.c
  41. 32
      lib/efi_loader/efi_smbios.c
  42. 82
      lib/smbios.c
  43. 20
      lib/tables_csum.c

@ -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,36 @@ 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(&regs);
else
hvc_call(&regs);
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(&regs);
else
hvc_call(&regs);
@ -89,3 +113,30 @@ void __noreturn psci_system_reset(bool conduit_smc)
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 */

@ -107,15 +107,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[] = {

@ -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

@ -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_ */

@ -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;

@ -34,6 +34,19 @@ 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
*
* When allocating memory we should always start from the highest
@ -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,
};

@ -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;

@ -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…
Cancel
Save