mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-03-16 23:07:00 +00:00
Patch queue for efi - 2018-06-03
A number of fixes and feature completeness work this time around: - Fix sunxi GOP reservation - Fix cursor position - Fix efi_get_variable - Allow more selftest parts to build on x86_64 - Allow unaligned memory access on armv7 - Implement ReinstallProtocolInterface - More sandbox preparation -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJbE/PWAAoJECszeR4D/txgp3wQAJyk8Y0N4ZpA9O3R/D8jvXvE nnk7UfRzIYx5qKFJ6yBRvPh//hjswD9ihNQ5/oVw62pqA1J28jCFDfGmIdDYVSk6 Itxvyx9O7DQBC4b1sHi5P5euZU/IuxQkUDszI1vOGhgt3al335EEliB4CWuRms2d mpOEm39o7eAcBtNTvbER9S+baDmFIcCMrCol/ayVLWwkd6B7X30GtzXCu9mHjoov M6KObSLh7lT0gqvYpHoCKIJR9q8b93tIqYyGuk+bBsZmo5IuuuQXqmhoB9LQ/M+p mQklJdXorJfk7/kks++I99WaPejcS5U679+A7RCPNiQM1ItavirpbosjdL1F8S5j EBsIxTBMnJhR/oQ1KEqRSiIIMzch/M1a6ikJr08Poy5wKVGJfSfJ69DDKCtmeEf+ 5aKNco0q23XcJa/Thc5BNr1wVM7QvhC0NszrvS6aG2IkkvGsKrD3xtB6J2aQeZlc JflYPtIELIT8RMn0zeFhNtA9KYCZINCq5Kn4jXz9zAD6vKHfQX1/sdAtojEjNblq e7A6aky8e2vHeiYPcz8HbFXwA6wL4qB70BIAYdqZQ73QZGz4bVTtk5YM5pjpHZYk uRjQWie+dwtB5EzuWAa1v63EcpM10kL0r3Dfv2bJt70iWzST7xtg4sH4xW1ekL8p q/mGsroVPJdI2byEbeol =gcE4 -----END PGP SIGNATURE----- Merge tag 'signed-efi-next' of git://github.com/agraf/u-boot Patch queue for efi - 2018-06-03 A number of fixes and feature completeness work this time around: - Fix sunxi GOP reservation - Fix cursor position - Fix efi_get_variable - Allow more selftest parts to build on x86_64 - Allow unaligned memory access on armv7 - Implement ReinstallProtocolInterface - More sandbox preparation
This commit is contained in:
commit
a0115ceb56
43 changed files with 1299 additions and 588 deletions
|
@ -342,6 +342,7 @@ EFI PAYLOAD
|
|||
M: Alexander Graf <agraf@suse.de>
|
||||
S: Maintained
|
||||
T: git git://github.com/agraf/u-boot.git
|
||||
F: doc/DocBook/efi.tmpl
|
||||
F: doc/README.uefi
|
||||
F: doc/README.iscsi
|
||||
F: include/efi*
|
||||
|
|
3
Makefile
3
Makefile
|
@ -1625,7 +1625,8 @@ clean: $(clean-dirs)
|
|||
-o -name '*.symtypes' -o -name 'modules.order' \
|
||||
-o -name modules.builtin -o -name '.tmp_*.o.*' \
|
||||
-o -name 'dsdt.aml' -o -name 'dsdt.asl.tmp' -o -name 'dsdt.c' \
|
||||
-o -name '*.gcno' \) -type f -print | xargs rm -f
|
||||
-o -name '*.efi' -o -name '*.gcno' -o -name '*.so' \) \
|
||||
-type f -print | xargs rm -f
|
||||
|
||||
# mrproper - Delete all generated files, including .config
|
||||
#
|
||||
|
|
|
@ -12,6 +12,10 @@ obj-y += syslib.o
|
|||
|
||||
obj-$(CONFIG_SYS_ARM_MPU) += mpu_v7r.o
|
||||
|
||||
ifneq ($(CONFIG_SPL_BUILD),y)
|
||||
obj-$(CONFIG_EFI_LOADER) += sctlr.o
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y)
|
||||
obj-y += lowlevel_init.o
|
||||
endif
|
||||
|
|
22
arch/arm/cpu/armv7/sctlr.S
Normal file
22
arch/arm/cpu/armv7/sctlr.S
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Routines to access the system control register
|
||||
*
|
||||
* Copyright (c) 2018 Heinrich Schuchardt
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/*
|
||||
* void allow_unaligned(void) - allow unaligned access
|
||||
*
|
||||
* This routine clears the aligned flag in the system control register.
|
||||
* After calling this routine unaligned access does no longer lead to a
|
||||
* data abort but is handled by the CPU.
|
||||
*/
|
||||
ENTRY(allow_unaligned)
|
||||
mrc p15, 0, r0, c1, c0, 0 @ load system control register
|
||||
bic r0, r0, #2 @ clear aligned flag
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write system control register
|
||||
bx lr @ return
|
||||
ENDPROC(allow_unaligned)
|
|
@ -37,7 +37,6 @@ int arch_early_init_r(void);
|
|||
|
||||
/* board/.../... */
|
||||
int board_init(void);
|
||||
void board_quiesce_devices(void);
|
||||
|
||||
/* cpu/.../interrupt.c */
|
||||
int arch_interrupt_init (void);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/libfdt.h>
|
||||
#include <os.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/setjmp.h>
|
||||
#include <asm/state.h>
|
||||
#include <dm/root.h>
|
||||
|
||||
|
@ -164,3 +165,15 @@ ulong timer_get_boot_us(void)
|
|||
|
||||
return (count - base_count) / 1000;
|
||||
}
|
||||
|
||||
int setjmp(jmp_buf jmp)
|
||||
{
|
||||
return os_setjmp((ulong *)jmp, sizeof(*jmp));
|
||||
}
|
||||
|
||||
void longjmp(jmp_buf jmp, int ret)
|
||||
{
|
||||
os_longjmp((ulong *)jmp, ret);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -628,3 +629,25 @@ void os_localtime(struct rtc_time *rt)
|
|||
rt->tm_yday = tm->tm_yday;
|
||||
rt->tm_isdst = tm->tm_isdst;
|
||||
}
|
||||
|
||||
int os_setjmp(ulong *jmp, int size)
|
||||
{
|
||||
jmp_buf dummy;
|
||||
|
||||
/*
|
||||
* We cannot rely on the struct name that jmp_buf uses, so use a
|
||||
* local variable here
|
||||
*/
|
||||
if (size < sizeof(dummy)) {
|
||||
printf("setjmp: jmpbuf is too small (%d bytes, need %d)\n",
|
||||
size, sizeof(jmp_buf));
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
return setjmp((struct __jmp_buf_tag *)jmp);
|
||||
}
|
||||
|
||||
void os_longjmp(ulong *jmp, int ret)
|
||||
{
|
||||
longjmp((struct __jmp_buf_tag *)jmp, ret);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,35 @@ SECTIONS
|
|||
__u_boot_sandbox_option_end = .;
|
||||
|
||||
__bss_start = .;
|
||||
|
||||
.__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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
INSERT BEFORE .data;
|
||||
|
|
30
arch/sandbox/include/asm/setjmp.h
Normal file
30
arch/sandbox/include/asm/setjmp.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) 2018 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#ifndef _SETJMP_H_
|
||||
#define _SETJMP_H_
|
||||
|
||||
struct jmp_buf_data {
|
||||
/*
|
||||
* We're not sure how long this should be:
|
||||
*
|
||||
* amd64: 200 bytes
|
||||
* arm64: 392 bytes
|
||||
* armhf: 392 bytes
|
||||
*
|
||||
* So allow space for all of those, plus some extra.
|
||||
* We don't need to worry about 16-byte alignment, since this does not
|
||||
* run on Windows.
|
||||
*/
|
||||
ulong data[128];
|
||||
};
|
||||
|
||||
typedef struct jmp_buf_data jmp_buf[1];
|
||||
|
||||
int setjmp(jmp_buf jmp);
|
||||
__noreturn void longjmp(jmp_buf jmp, int ret);
|
||||
|
||||
#endif /* _SETJMP_H_ */
|
|
@ -5,7 +5,7 @@
|
|||
# (C) Copyright 2002-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
|
||||
obj-y += interrupts.o
|
||||
obj-y += interrupts.o sections.o
|
||||
obj-$(CONFIG_PCI) += pci_io.o
|
||||
obj-$(CONFIG_CMD_BOOTM) += bootm.o
|
||||
obj-$(CONFIG_CMD_BOOTZ) += bootm.o
|
||||
|
|
12
arch/sandbox/lib/sections.c
Normal file
12
arch/sandbox/lib/sections.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2013 Albert ARIBAUD <albert.u.boot@aribaud.net>
|
||||
*
|
||||
*/
|
||||
|
||||
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")));
|
|
@ -86,9 +86,9 @@ else
|
|||
PLATFORM_CPPFLAGS += -D__I386__
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),)
|
||||
ifdef CONFIG_EFI_STUB
|
||||
|
||||
ifneq ($(CONFIG_EFI_STUB_64BIT),)
|
||||
ifdef CONFIG_EFI_STUB_64BIT
|
||||
EFI_LDS := elf_x86_64_efi.lds
|
||||
EFI_CRT0 := crt0_x86_64_efi.o
|
||||
EFI_RELOC := reloc_x86_64_efi.o
|
||||
|
@ -98,10 +98,22 @@ EFI_CRT0 := crt0_ia32_efi.o
|
|||
EFI_RELOC := reloc_ia32_efi.o
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
ifdef CONFIG_X86_64
|
||||
EFI_LDS := elf_x86_64_efi.lds
|
||||
EFI_CRT0 := crt0_x86_64_efi.o
|
||||
EFI_RELOC := reloc_x86_64_efi.o
|
||||
else
|
||||
EFI_LDS := elf_ia32_efi.lds
|
||||
EFI_CRT0 := crt0_ia32_efi.o
|
||||
EFI_RELOC := reloc_ia32_efi.o
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifdef CONFIG_X86_64
|
||||
EFI_TARGET := --target=efi-app-x86_64
|
||||
else
|
||||
EFI_TARGET := --target=efi-app-ia32
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -84,7 +84,6 @@ static inline __attribute__((no_instrument_function)) uint64_t rdtsc(void)
|
|||
/* board/... */
|
||||
void timer_set_tsc_base(uint64_t new_base);
|
||||
uint64_t timer_get_tsc(void);
|
||||
void board_quiesce_devices(void);
|
||||
|
||||
void quick_ram_check(void);
|
||||
|
||||
|
|
|
@ -68,8 +68,18 @@ extra-$(CONFIG_EFI_STUB_64BIT) += crt0_x86_64_efi.o reloc_x86_64_efi.o
|
|||
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_EFI_STUB)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),)
|
||||
ifdef CONFIG_EFI_STUB
|
||||
|
||||
ifeq ($(CONFIG_$(SPL_)X86_64),)
|
||||
extra-y += $(EFI_CRT0) $(EFI_RELOC)
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST)$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),)
|
||||
extra-y += $(EFI_CRT0) $(EFI_RELOC)
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
|
@ -27,10 +27,6 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
|
||||
#define COMMAND_LINE_OFFSET 0x9000
|
||||
|
||||
__weak void board_quiesce_devices(void)
|
||||
{
|
||||
}
|
||||
|
||||
void bootm_announce_and_cleanup(void)
|
||||
{
|
||||
printf("\nStarting kernel ...\n\n");
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <memalign.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm-generic/sections.h>
|
||||
#include <asm-generic/unaligned.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
@ -82,6 +83,15 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow unaligned memory access.
|
||||
*
|
||||
* This routine is overridden by architectures providing this feature.
|
||||
*/
|
||||
void __weak allow_unaligned(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the load options of an image from an environment variable.
|
||||
*
|
||||
|
@ -133,11 +143,13 @@ static void *copy_fdt(void *fdt)
|
|||
|
||||
/* Safe fdt location is at 128MB */
|
||||
new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size;
|
||||
if (efi_allocate_pages(1, EFI_RUNTIME_SERVICES_DATA, fdt_pages,
|
||||
if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
|
||||
EFI_RUNTIME_SERVICES_DATA, fdt_pages,
|
||||
&new_fdt_addr) != EFI_SUCCESS) {
|
||||
/* If we can't put it there, put it somewhere */
|
||||
new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
|
||||
if (efi_allocate_pages(1, EFI_RUNTIME_SERVICES_DATA, fdt_pages,
|
||||
if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
|
||||
EFI_RUNTIME_SERVICES_DATA, fdt_pages,
|
||||
&new_fdt_addr) != EFI_SUCCESS) {
|
||||
printf("ERROR: Failed to reserve space for FDT\n");
|
||||
return NULL;
|
||||
|
@ -370,6 +382,9 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
efi_status_t r;
|
||||
void *fdt_addr;
|
||||
|
||||
/* Allow unaligned memory access */
|
||||
allow_unaligned();
|
||||
|
||||
/* Initialize EFI drivers */
|
||||
r = efi_init_obj_list();
|
||||
if (r != EFI_SUCCESS) {
|
||||
|
@ -428,8 +443,6 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|||
* callback entry
|
||||
*/
|
||||
efi_save_gd();
|
||||
/* Initialize and populate EFI object list */
|
||||
efi_init_obj_list();
|
||||
/* Transfer environment variable efi_selftest as load options */
|
||||
set_load_options(&loaded_image_info, "efi_selftest");
|
||||
/* Execute the test */
|
||||
|
|
|
@ -46,6 +46,10 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
|
|||
char * const argv[], bootm_headers_t *images,
|
||||
ulong *os_data, ulong *os_len);
|
||||
|
||||
__weak void board_quiesce_devices(void)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LMB
|
||||
static void boot_start_lmb(bootm_headers_t *images)
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# To add a new book the only step required is to add the book to the
|
||||
# list of DOCBOOKS.
|
||||
|
||||
DOCBOOKS := linker_lists.xml stdio.xml
|
||||
DOCBOOKS := efi.xml linker_lists.xml stdio.xml
|
||||
|
||||
###
|
||||
# The build process is as follows (targets):
|
||||
|
|
17
doc/DocBook/efi.tmpl
Normal file
17
doc/DocBook/efi.tmpl
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
|
||||
|
||||
<book id="UBootEFI">
|
||||
<bookinfo>
|
||||
<title>The U-Boot EFI subsystem</title>
|
||||
</bookinfo>
|
||||
|
||||
<toc></toc>
|
||||
|
||||
<chapter id="BootServices">
|
||||
<title>Boot services</title>
|
||||
!Ilib/efi_loader/efi_boottime.c
|
||||
</chapter>
|
||||
|
||||
</book>
|
|
@ -299,13 +299,18 @@ This driver is only available if U-Boot is configured with
|
|||
CONFIG_BLK=y
|
||||
CONFIG_PARTITIONS=y
|
||||
|
||||
## TODOs as of U-Boot 2018.03
|
||||
## TODOs as of U-Boot 2018.07
|
||||
|
||||
* unimplemented or incompletely implemented boot services
|
||||
* Exit - call unload function, unload applications only
|
||||
* ReinstallProtocolInterface
|
||||
* ProtocolRegisterNotify
|
||||
* UnloadImage
|
||||
|
||||
* unimplemented or incompletely implemented runtime services
|
||||
* SetVariable() ignores attribute EFI_VARIABLE_APPEND_WRITE
|
||||
* GetNextVariableName is not implemented
|
||||
* QueryVariableInfo is not implemented
|
||||
|
||||
* unimplemented events
|
||||
* EVT_RUNTIME
|
||||
* EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <display.h>
|
||||
#include <dm.h>
|
||||
#include <edid.h>
|
||||
#include <efi_loader.h>
|
||||
#include <fdtdec.h>
|
||||
#include <fdt_support.h>
|
||||
#include <video.h>
|
||||
|
@ -221,6 +222,13 @@ static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
|
|||
uc_priv->bpix = l2bpp;
|
||||
debug("fb=%lx, size=%d %d\n", fbbase, uc_priv->xsize, uc_priv->ysize);
|
||||
|
||||
#ifdef CONFIG_EFI_LOADER
|
||||
efi_add_memory_map(fbbase,
|
||||
ALIGN(timing.hactive.typ * timing.vactive.typ *
|
||||
(1 << l2bpp) / 8, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
||||
EFI_RESERVED_MEMORY_TYPE, false);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,4 +20,7 @@
|
|||
#error invalid endian
|
||||
#endif
|
||||
|
||||
/* Allow unaligned memory access */
|
||||
void allow_unaligned(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -72,4 +72,12 @@ int bootm_decomp_image(int comp, ulong load, ulong image_start, int type,
|
|||
void *load_buf, void *image_buf, ulong image_len,
|
||||
uint unc_len, ulong *load_end);
|
||||
|
||||
/*
|
||||
* boards should define this to disable devices when EFI exits from boot
|
||||
* services.
|
||||
*
|
||||
* TODO(sjg@chromium.org>): Update this to use driver model's device_remove().
|
||||
*/
|
||||
void board_quiesce_devices(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -214,15 +214,15 @@ struct efi_runtime_services {
|
|||
uint32_t descriptor_version,
|
||||
struct efi_mem_desc *virtmap);
|
||||
efi_status_t (*convert_pointer)(unsigned long dbg, void **address);
|
||||
efi_status_t (EFIAPI *get_variable)(s16 *variable_name,
|
||||
efi_guid_t *vendor, u32 *attributes,
|
||||
unsigned long *data_size, void *data);
|
||||
efi_status_t (EFIAPI *get_next_variable)(
|
||||
unsigned long *variable_name_size,
|
||||
s16 *variable_name, efi_guid_t *vendor);
|
||||
efi_status_t (EFIAPI *set_variable)(s16 *variable_name,
|
||||
efi_guid_t *vendor, u32 attributes,
|
||||
unsigned long data_size, void *data);
|
||||
efi_status_t (EFIAPI *get_variable)(u16 *variable_name,
|
||||
efi_guid_t *vendor, u32 *attributes,
|
||||
efi_uintn_t *data_size, void *data);
|
||||
efi_status_t (EFIAPI *get_next_variable_name)(
|
||||
efi_uintn_t *variable_name_size,
|
||||
u16 *variable_name, efi_guid_t *vendor);
|
||||
efi_status_t (EFIAPI *set_variable)(u16 *variable_name,
|
||||
efi_guid_t *vendor, u32 attributes,
|
||||
efi_uintn_t data_size, void *data);
|
||||
efi_status_t (EFIAPI *get_next_high_mono_count)(
|
||||
uint32_t *high_count);
|
||||
void (EFIAPI *reset_system)(enum efi_reset_type reset_type,
|
||||
|
@ -239,9 +239,9 @@ struct efi_runtime_services {
|
|||
u32 reset_type);
|
||||
efi_status_t (EFIAPI *query_variable_info)(
|
||||
u32 attributes,
|
||||
u64 maximum_variable_storage_size,
|
||||
u64 remaining_variable_storage_size,
|
||||
u64 maximum_variable_size);
|
||||
u64 *maximum_variable_storage_size,
|
||||
u64 *remaining_variable_storage_size,
|
||||
u64 *maximum_variable_size);
|
||||
};
|
||||
|
||||
/* EFI event group GUID definitions */
|
||||
|
|
|
@ -214,6 +214,13 @@ efi_status_t efi_net_register(void);
|
|||
/* Called by bootefi to make the watchdog available */
|
||||
efi_status_t efi_watchdog_register(void);
|
||||
/* Called by bootefi to make SMBIOS tables available */
|
||||
/**
|
||||
* efi_smbios_register() - write out SMBIOS tables
|
||||
*
|
||||
* Called by bootefi to make SMBIOS tables available
|
||||
*
|
||||
* @return 0 if OK, -ENOMEM if no memory is available for the tables
|
||||
*/
|
||||
efi_status_t efi_smbios_register(void);
|
||||
|
||||
struct efi_simple_file_system_protocol *
|
||||
|
@ -422,15 +429,15 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,
|
|||
struct efi_system_table *systab);
|
||||
#endif
|
||||
|
||||
efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
|
||||
efi_guid_t *vendor, u32 *attributes,
|
||||
unsigned long *data_size, void *data);
|
||||
efi_status_t EFIAPI efi_get_next_variable(
|
||||
unsigned long *variable_name_size,
|
||||
s16 *variable_name, efi_guid_t *vendor);
|
||||
efi_status_t EFIAPI efi_set_variable(s16 *variable_name,
|
||||
efi_guid_t *vendor, u32 attributes,
|
||||
unsigned long data_size, void *data);
|
||||
efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor,
|
||||
u32 *attributes, efi_uintn_t *data_size,
|
||||
void *data);
|
||||
efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
|
||||
u16 *variable_name,
|
||||
efi_guid_t *vendor);
|
||||
efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor,
|
||||
u32 attributes, efi_uintn_t data_size,
|
||||
void *data);
|
||||
|
||||
void *efi_bootmgr_load(struct efi_device_path **device_path,
|
||||
struct efi_device_path **file_path);
|
||||
|
|
21
include/os.h
21
include/os.h
|
@ -330,4 +330,25 @@ int os_spl_to_uboot(const char *fname);
|
|||
*/
|
||||
void os_localtime(struct rtc_time *rt);
|
||||
|
||||
/**
|
||||
* os_setjmp() - Call setjmp()
|
||||
*
|
||||
* Call the host system's setjmp() function.
|
||||
*
|
||||
* @jmp: Buffer to store current execution state
|
||||
* @size: Size of buffer
|
||||
* @return normal setjmp() value if OK, -ENOSPC if @size is too small
|
||||
*/
|
||||
int os_setjmp(ulong *jmp, int size);
|
||||
|
||||
/**
|
||||
* os_longjmp() - Call longjmp()
|
||||
*
|
||||
* Call the host system's longjmp() function.
|
||||
*
|
||||
* @jmp: Buffer where previous execution state was stored
|
||||
* @ret: Value to pass to longjmp()
|
||||
*/
|
||||
void os_longjmp(ulong *jmp, int ret);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -231,8 +231,9 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
|
|||
*
|
||||
* This writes SMBIOS table at a given address.
|
||||
*
|
||||
* @addr: start address to write SMBIOS table
|
||||
* @return: end address of SMBIOS table
|
||||
* @addr: start address to write SMBIOS table. If this is not
|
||||
* 16-byte-aligned then it will be aligned before the table is written
|
||||
* @return: end address of SMBIOS table (and start address for next entry)
|
||||
*/
|
||||
ulong write_smbios_table(ulong addr);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ config EFI_LOADER
|
|||
default y
|
||||
select LIB_UUID
|
||||
select HAVE_BLOCK_DEVICE
|
||||
imply CFB_CONSOLE_ANSI
|
||||
help
|
||||
Select this option if you want to run EFI applications (like grub2)
|
||||
on top of U-Boot. If this option is enabled, U-Boot will expose EFI
|
||||
|
|
|
@ -70,17 +70,17 @@ static void parse_load_option(struct load_option *lo, void *ptr)
|
|||
|
||||
/* free() the result */
|
||||
static void *get_var(u16 *name, const efi_guid_t *vendor,
|
||||
unsigned long *size)
|
||||
efi_uintn_t *size)
|
||||
{
|
||||
efi_guid_t *v = (efi_guid_t *)vendor;
|
||||
efi_status_t ret;
|
||||
void *buf = NULL;
|
||||
|
||||
*size = 0;
|
||||
EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf));
|
||||
EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf));
|
||||
if (ret == EFI_BUFFER_TOO_SMALL) {
|
||||
buf = malloc(*size);
|
||||
EFI_CALL(ret = rs->get_variable((s16 *)name, v, NULL, size, buf));
|
||||
EFI_CALL(ret = rs->get_variable(name, v, NULL, size, buf));
|
||||
}
|
||||
|
||||
if (ret != EFI_SUCCESS) {
|
||||
|
@ -104,7 +104,7 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path,
|
|||
u16 varname[] = L"Boot0000";
|
||||
u16 hexmap[] = L"0123456789ABCDEF";
|
||||
void *load_option, *image = NULL;
|
||||
unsigned long size;
|
||||
efi_uintn_t size;
|
||||
|
||||
varname[4] = hexmap[(n & 0xf000) >> 12];
|
||||
varname[5] = hexmap[(n & 0x0f00) >> 8];
|
||||
|
@ -147,7 +147,7 @@ void *efi_bootmgr_load(struct efi_device_path **device_path,
|
|||
struct efi_device_path **file_path)
|
||||
{
|
||||
uint16_t *bootorder;
|
||||
unsigned long size;
|
||||
efi_uintn_t size;
|
||||
void *image = NULL;
|
||||
int i, num;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,8 +12,6 @@
|
|||
#include <stdio_dev.h>
|
||||
#include <video_console.h>
|
||||
|
||||
static bool console_size_queried;
|
||||
|
||||
#define EFI_COUT_MODE_2 2
|
||||
#define EFI_MAX_COUT_MODE 3
|
||||
|
||||
|
@ -62,7 +60,15 @@ static struct simple_text_output_mode efi_con_mode = {
|
|||
.cursor_visible = 1,
|
||||
};
|
||||
|
||||
static int term_read_reply(int *n, int maxnum, char end_char)
|
||||
/*
|
||||
* Receive and parse a reply from the terminal.
|
||||
*
|
||||
* @n: array of return values
|
||||
* @num: number of return values expected
|
||||
* @end_char: character indicating end of terminal message
|
||||
* @return: non-zero indicates error
|
||||
*/
|
||||
static int term_read_reply(int *n, int num, char end_char)
|
||||
{
|
||||
char c;
|
||||
int i = 0;
|
||||
|
@ -79,7 +85,7 @@ static int term_read_reply(int *n, int maxnum, char end_char)
|
|||
c = getc();
|
||||
if (c == ';') {
|
||||
i++;
|
||||
if (i >= maxnum)
|
||||
if (i >= num)
|
||||
return -1;
|
||||
n[i] = 0;
|
||||
continue;
|
||||
|
@ -93,6 +99,8 @@ static int term_read_reply(int *n, int maxnum, char end_char)
|
|||
n[i] *= 10;
|
||||
n[i] += c - '0';
|
||||
}
|
||||
if (i != num - 1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -116,25 +124,36 @@ static efi_status_t EFIAPI efi_cout_output_string(
|
|||
|
||||
unsigned int n16 = utf16_strlen(string);
|
||||
char buf[MAX_UTF8_PER_UTF16 * n16 + 1];
|
||||
char *p;
|
||||
u16 *p;
|
||||
|
||||
*utf16_to_utf8((u8 *)buf, string, n16) = '\0';
|
||||
|
||||
fputs(stdout, buf);
|
||||
|
||||
for (p = buf; *p; p++) {
|
||||
/*
|
||||
* Update the cursor position.
|
||||
*
|
||||
* The UEFI spec provides advance rules for U+0000, U+0008, U+000A,
|
||||
* and U000D. All other characters, including control characters
|
||||
* U+0007 (bel) and U+0009 (tab), have to increase the column by one.
|
||||
*/
|
||||
for (p = string; *p; ++p) {
|
||||
switch (*p) {
|
||||
case '\r': /* carriage-return */
|
||||
con->cursor_column = 0;
|
||||
case '\b': /* U+0008, backspace */
|
||||
con->cursor_column = max(0, con->cursor_column - 1);
|
||||
break;
|
||||
case '\n': /* newline */
|
||||
case '\n': /* U+000A, newline */
|
||||
con->cursor_column = 0;
|
||||
con->cursor_row++;
|
||||
break;
|
||||
case '\t': /* tab, assume 8 char align */
|
||||
case '\r': /* U+000D, carriage-return */
|
||||
con->cursor_column = 0;
|
||||
break;
|
||||
case '\b': /* backspace */
|
||||
con->cursor_column = max(0, con->cursor_column - 1);
|
||||
case 0xd800 ... 0xdbff:
|
||||
/*
|
||||
* Ignore high surrogates, we do not want to count a
|
||||
* Unicode character twice.
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
con->cursor_column++;
|
||||
|
@ -194,6 +213,51 @@ static int query_console_serial(int *rows, int *cols)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the mode table.
|
||||
*
|
||||
* By default the only mode available is 80x25. If the console has at least 50
|
||||
* lines, enable mode 80x50. If we can query the console size and it is neither
|
||||
* 80x25 nor 80x50, set it as an additional mode.
|
||||
*/
|
||||
static void query_console_size(void)
|
||||
{
|
||||
const char *stdout_name = env_get("stdout");
|
||||
int rows = 25, cols = 80;
|
||||
|
||||
if (stdout_name && !strcmp(stdout_name, "vidconsole") &&
|
||||
IS_ENABLED(CONFIG_DM_VIDEO)) {
|
||||
struct stdio_dev *stdout_dev =
|
||||
stdio_get_by_name("vidconsole");
|
||||
struct udevice *dev = stdout_dev->priv;
|
||||
struct vidconsole_priv *priv =
|
||||
dev_get_uclass_priv(dev);
|
||||
rows = priv->rows;
|
||||
cols = priv->cols;
|
||||
} else if (query_console_serial(&rows, &cols)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test if we can have Mode 1 */
|
||||
if (cols >= 80 && rows >= 50) {
|
||||
efi_cout_modes[1].present = 1;
|
||||
efi_con_mode.max_mode = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install our mode as mode 2 if it is different
|
||||
* than mode 0 or 1 and set it as the currently selected mode
|
||||
*/
|
||||
if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) &&
|
||||
!cout_mode_matches(&efi_cout_modes[1], rows, cols)) {
|
||||
efi_cout_modes[EFI_COUT_MODE_2].columns = cols;
|
||||
efi_cout_modes[EFI_COUT_MODE_2].rows = rows;
|
||||
efi_cout_modes[EFI_COUT_MODE_2].present = 1;
|
||||
efi_con_mode.max_mode = EFI_MAX_COUT_MODE;
|
||||
efi_con_mode.mode = EFI_COUT_MODE_2;
|
||||
}
|
||||
}
|
||||
|
||||
static efi_status_t EFIAPI efi_cout_query_mode(
|
||||
struct efi_simple_text_output_protocol *this,
|
||||
unsigned long mode_number, unsigned long *columns,
|
||||
|
@ -201,52 +265,12 @@ static efi_status_t EFIAPI efi_cout_query_mode(
|
|||
{
|
||||
EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
|
||||
|
||||
if (!console_size_queried) {
|
||||
const char *stdout_name = env_get("stdout");
|
||||
int rows, cols;
|
||||
|
||||
console_size_queried = true;
|
||||
|
||||
if (stdout_name && !strcmp(stdout_name, "vidconsole") &&
|
||||
IS_ENABLED(CONFIG_DM_VIDEO)) {
|
||||
struct stdio_dev *stdout_dev =
|
||||
stdio_get_by_name("vidconsole");
|
||||
struct udevice *dev = stdout_dev->priv;
|
||||
struct vidconsole_priv *priv =
|
||||
dev_get_uclass_priv(dev);
|
||||
rows = priv->rows;
|
||||
cols = priv->cols;
|
||||
} else if (query_console_serial(&rows, &cols)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Test if we can have Mode 1 */
|
||||
if (cols >= 80 && rows >= 50) {
|
||||
efi_cout_modes[1].present = 1;
|
||||
efi_con_mode.max_mode = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install our mode as mode 2 if it is different
|
||||
* than mode 0 or 1 and set it as the currently selected mode
|
||||
*/
|
||||
if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) &&
|
||||
!cout_mode_matches(&efi_cout_modes[1], rows, cols)) {
|
||||
efi_cout_modes[EFI_COUT_MODE_2].columns = cols;
|
||||
efi_cout_modes[EFI_COUT_MODE_2].rows = rows;
|
||||
efi_cout_modes[EFI_COUT_MODE_2].present = 1;
|
||||
efi_con_mode.max_mode = EFI_MAX_COUT_MODE;
|
||||
efi_con_mode.mode = EFI_COUT_MODE_2;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode_number >= efi_con_mode.max_mode)
|
||||
return EFI_EXIT(EFI_UNSUPPORTED);
|
||||
|
||||
if (efi_cout_modes[mode_number].present != 1)
|
||||
return EFI_EXIT(EFI_UNSUPPORTED);
|
||||
|
||||
out:
|
||||
if (columns)
|
||||
*columns = efi_cout_modes[mode_number].columns;
|
||||
if (rows)
|
||||
|
@ -554,6 +578,9 @@ int efi_console_register(void)
|
|||
struct efi_object *efi_console_output_obj;
|
||||
struct efi_object *efi_console_input_obj;
|
||||
|
||||
/* Set up mode information */
|
||||
query_console_size();
|
||||
|
||||
/* Create handles */
|
||||
r = efi_create_handle((efi_handle_t *)&efi_console_output_obj);
|
||||
if (r != EFI_SUCCESS)
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <common.h>
|
||||
#include <efi_loader.h>
|
||||
#include <pe.h>
|
||||
#include <asm/global_data.h>
|
||||
|
||||
const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
|
||||
const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID;
|
||||
|
@ -90,11 +89,16 @@ void efi_print_image_infos(void *pc)
|
|||
}
|
||||
|
||||
static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
|
||||
unsigned long rel_size, void *efi_reloc)
|
||||
unsigned long rel_size, void *efi_reloc,
|
||||
unsigned long pref_address)
|
||||
{
|
||||
unsigned long delta = (unsigned long)efi_reloc - pref_address;
|
||||
const IMAGE_BASE_RELOCATION *end;
|
||||
int i;
|
||||
|
||||
if (delta == 0)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size);
|
||||
while (rel < end - 1 && rel->SizeOfBlock) {
|
||||
const uint16_t *relocs = (const uint16_t *)(rel + 1);
|
||||
|
@ -103,7 +107,6 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel,
|
|||
uint32_t offset = (uint32_t)(*relocs & 0xfff) +
|
||||
rel->VirtualAddress;
|
||||
int type = *relocs >> EFI_PAGE_SHIFT;
|
||||
unsigned long delta = (unsigned long)efi_reloc;
|
||||
uint64_t *x64 = efi_reloc + offset;
|
||||
uint32_t *x32 = efi_reloc + offset;
|
||||
uint16_t *x16 = efi_reloc + offset;
|
||||
|
@ -191,6 +194,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
|
|||
unsigned long rel_size;
|
||||
int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC;
|
||||
void *entry;
|
||||
uint64_t image_base;
|
||||
uint64_t image_size;
|
||||
unsigned long virt_size = 0;
|
||||
int supported = 0;
|
||||
|
@ -234,6 +238,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
|
|||
if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
|
||||
IMAGE_NT_HEADERS64 *nt64 = (void *)nt;
|
||||
IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
|
||||
image_base = opt->ImageBase;
|
||||
image_size = opt->SizeOfImage;
|
||||
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
||||
efi_reloc = efi_alloc(virt_size,
|
||||
|
@ -249,6 +254,7 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
|
|||
virt_size = ALIGN(virt_size, opt->SectionAlignment);
|
||||
} else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
|
||||
IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
|
||||
image_base = opt->ImageBase;
|
||||
image_size = opt->SizeOfImage;
|
||||
efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
|
||||
efi_reloc = efi_alloc(virt_size,
|
||||
|
@ -279,7 +285,8 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info)
|
|||
}
|
||||
|
||||
/* Run through relocations */
|
||||
if (efi_loader_relocate(rel, rel_size, efi_reloc) != EFI_SUCCESS) {
|
||||
if (efi_loader_relocate(rel, rel_size, efi_reloc,
|
||||
(unsigned long)image_base) != EFI_SUCCESS) {
|
||||
efi_free_pages((uintptr_t) efi_reloc,
|
||||
(virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT);
|
||||
return NULL;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <inttypes.h>
|
||||
#include <malloc.h>
|
||||
#include <watchdog.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <linux/list_sort.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
@ -69,23 +68,27 @@ static void efi_mem_sort(void)
|
|||
list_sort(NULL, &efi_mem, efi_mem_cmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmaps all memory occupied by the carve_desc region from the
|
||||
* list entry pointed to by map.
|
||||
/** efi_mem_carve_out - unmap memory region
|
||||
*
|
||||
* 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.
|
||||
* @map: memory map
|
||||
* @carve_desc: memory region to unmap
|
||||
* @overlap_only_ram: the carved out region may only overlap RAM
|
||||
* Return Value: the number of overlapping pages which have been
|
||||
* removed from the map,
|
||||
* EFI_CARVE_NO_OVERLAP, if the regions don't overlap,
|
||||
* 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),
|
||||
* EFI_CARVE_LOOP_AGAIN, if the mapping list should be
|
||||
* traversed again, as it has been altered.
|
||||
*
|
||||
* Unmaps all memory occupied by the carve_desc region from the list entry
|
||||
* pointed to by map.
|
||||
*
|
||||
* In case of EFI_CARVE_OVERLAPS_NONRAM it is the callers responsibility
|
||||
* to readd the already carved out pages to the mapping.
|
||||
* to re-add the already carved out pages to the mapping.
|
||||
*/
|
||||
static int efi_mem_carve_out(struct efi_mem_list *map,
|
||||
static s64 efi_mem_carve_out(struct efi_mem_list *map,
|
||||
struct efi_mem_desc *carve_desc,
|
||||
bool overlap_only_ram)
|
||||
{
|
||||
|
@ -184,7 +187,7 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
|
|||
carve_again = false;
|
||||
list_for_each(lhandle, &efi_mem) {
|
||||
struct efi_mem_list *lmem;
|
||||
int r;
|
||||
s64 r;
|
||||
|
||||
lmem = list_entry(lhandle, struct efi_mem_list, link);
|
||||
r = efi_mem_carve_out(lmem, &newlist->desc,
|
||||
|
@ -338,7 +341,8 @@ void *efi_alloc(uint64_t len, int memory_type)
|
|||
uint64_t pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
||||
efi_status_t r;
|
||||
|
||||
r = efi_allocate_pages(0, memory_type, pages, &ret);
|
||||
r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages,
|
||||
&ret);
|
||||
if (r == EFI_SUCCESS)
|
||||
return (void*)(uintptr_t)ret;
|
||||
|
||||
|
@ -385,7 +389,8 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer)
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
r = efi_allocate_pages(0, pool_type, num_pages, &t);
|
||||
r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, pool_type, num_pages,
|
||||
&t);
|
||||
|
||||
if (r == EFI_SUCCESS) {
|
||||
struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
|
||||
|
@ -516,7 +521,7 @@ int efi_memory_init(void)
|
|||
/* Request a 32bit 64MB bounce buffer region */
|
||||
uint64_t efi_bounce_buffer_addr = 0xffffffff;
|
||||
|
||||
if (efi_allocate_pages(1, EFI_LOADER_DATA,
|
||||
if (efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA,
|
||||
(64 * 1024 * 1024) >> EFI_PAGE_SHIFT,
|
||||
&efi_bounce_buffer_addr) != EFI_SUCCESS)
|
||||
return -1;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <dm.h>
|
||||
#include <efi_loader.h>
|
||||
#include <rtc.h>
|
||||
#include <asm/global_data.h>
|
||||
|
||||
/* For manual relocation support */
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
@ -213,7 +212,7 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {
|
|||
.ptr = &efi_runtime_services.get_variable,
|
||||
.patchto = &efi_device_error,
|
||||
}, {
|
||||
.ptr = &efi_runtime_services.get_next_variable,
|
||||
.ptr = &efi_runtime_services.get_next_variable_name,
|
||||
.patchto = &efi_device_error,
|
||||
}, {
|
||||
.ptr = &efi_runtime_services.set_variable,
|
||||
|
@ -445,9 +444,9 @@ efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
|
|||
|
||||
efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
|
||||
u32 attributes,
|
||||
u64 maximum_variable_storage_size,
|
||||
u64 remaining_variable_storage_size,
|
||||
u64 maximum_variable_size)
|
||||
u64 *maximum_variable_storage_size,
|
||||
u64 *remaining_variable_storage_size,
|
||||
u64 *maximum_variable_size)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
@ -465,7 +464,7 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {
|
|||
.set_virtual_address_map = &efi_set_virtual_address_map,
|
||||
.convert_pointer = (void *)&efi_invalid_parameter,
|
||||
.get_variable = efi_get_variable,
|
||||
.get_next_variable = efi_get_next_variable,
|
||||
.get_next_variable_name = efi_get_next_variable_name,
|
||||
.set_variable = efi_set_variable,
|
||||
.get_next_high_mono_count = (void *)&efi_device_error,
|
||||
.reset_system = &efi_reset_system_boottime,
|
||||
|
|
|
@ -29,7 +29,12 @@ efi_status_t efi_smbios_register(void)
|
|||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
|
||||
/* Generate SMBIOS tables */
|
||||
/*
|
||||
* Generate SMBIOS tables - we know that efi_allocate_pages() returns
|
||||
* a 4k-aligned address, so it is safe to assume that
|
||||
* write_smbios_table() will write the table at that address.
|
||||
*/
|
||||
assert(!(dmi & 0xf));
|
||||
write_smbios_table(dmi);
|
||||
|
||||
/* And expose them to our EFI payload */
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
(strlen("efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_") + \
|
||||
(MAX_VAR_NAME * MAX_UTF8_PER_UTF16))
|
||||
|
||||
static int hex(unsigned char ch)
|
||||
static int hex(int ch)
|
||||
{
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
return ch-'a'+10;
|
||||
|
@ -60,44 +60,32 @@ static int hex(unsigned char ch)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static const char *hex2mem(u8 *mem, const char *hexstr, int count)
|
||||
static int hex2mem(u8 *mem, const char *hexstr, int size)
|
||||
{
|
||||
memset(mem, 0, count/2);
|
||||
int nibble;
|
||||
int i;
|
||||
|
||||
do {
|
||||
int nibble;
|
||||
|
||||
*mem = 0;
|
||||
|
||||
if (!count || !*hexstr)
|
||||
for (i = 0; i < size; i++) {
|
||||
if (*hexstr == '\0')
|
||||
break;
|
||||
|
||||
nibble = hex(*hexstr);
|
||||
if (nibble < 0)
|
||||
break;
|
||||
return -1;
|
||||
|
||||
*mem = nibble;
|
||||
count--;
|
||||
hexstr++;
|
||||
|
||||
if (!count || !*hexstr)
|
||||
break;
|
||||
|
||||
nibble = hex(*hexstr);
|
||||
if (nibble < 0)
|
||||
break;
|
||||
return -1;
|
||||
|
||||
*mem = (*mem << 4) | nibble;
|
||||
count--;
|
||||
hexstr++;
|
||||
mem++;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
|
||||
if (*hexstr)
|
||||
return hexstr;
|
||||
|
||||
return NULL;
|
||||
return i;
|
||||
}
|
||||
|
||||
static char *mem2hex(char *hexstr, const u8 *mem, int count)
|
||||
|
@ -113,8 +101,8 @@ static char *mem2hex(char *hexstr, const u8 *mem, int count)
|
|||
return hexstr;
|
||||
}
|
||||
|
||||
static efi_status_t efi_to_native(char *native, s16 *variable_name,
|
||||
efi_guid_t *vendor)
|
||||
static efi_status_t efi_to_native(char *native, u16 *variable_name,
|
||||
efi_guid_t *vendor)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
|
@ -176,9 +164,9 @@ static const char *parse_attr(const char *str, u32 *attrp)
|
|||
}
|
||||
|
||||
/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */
|
||||
efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
|
||||
efi_guid_t *vendor, u32 *attributes,
|
||||
unsigned long *data_size, void *data)
|
||||
efi_status_t EFIAPI efi_get_variable(u16 *variable_name, efi_guid_t *vendor,
|
||||
u32 *attributes, efi_uintn_t *data_size,
|
||||
void *data)
|
||||
{
|
||||
char native_name[MAX_NATIVE_VAR_NAME + 1];
|
||||
efi_status_t ret;
|
||||
|
@ -209,8 +197,12 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
|
|||
if ((s = prefix(val, "(blob)"))) {
|
||||
unsigned len = strlen(s);
|
||||
|
||||
/* number of hexadecimal digits must be even */
|
||||
if (len & 1)
|
||||
return EFI_EXIT(EFI_DEVICE_ERROR);
|
||||
|
||||
/* two characters per byte: */
|
||||
len = DIV_ROUND_UP(len, 2);
|
||||
len /= 2;
|
||||
*data_size = len;
|
||||
|
||||
if (in_size < len)
|
||||
|
@ -219,7 +211,7 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
|
|||
if (!data)
|
||||
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
||||
|
||||
if (hex2mem(data, s, len * 2))
|
||||
if (hex2mem(data, s, len) != len)
|
||||
return EFI_EXIT(EFI_DEVICE_ERROR);
|
||||
|
||||
debug("%s: got value: \"%s\"\n", __func__, s);
|
||||
|
@ -250,9 +242,9 @@ efi_status_t EFIAPI efi_get_variable(s16 *variable_name,
|
|||
}
|
||||
|
||||
/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */
|
||||
efi_status_t EFIAPI efi_get_next_variable(
|
||||
unsigned long *variable_name_size,
|
||||
s16 *variable_name, efi_guid_t *vendor)
|
||||
efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
|
||||
u16 *variable_name,
|
||||
efi_guid_t *vendor)
|
||||
{
|
||||
EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
|
||||
|
||||
|
@ -260,16 +252,16 @@ efi_status_t EFIAPI efi_get_next_variable(
|
|||
}
|
||||
|
||||
/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */
|
||||
efi_status_t EFIAPI efi_set_variable(s16 *variable_name,
|
||||
efi_guid_t *vendor, u32 attributes,
|
||||
unsigned long data_size, void *data)
|
||||
efi_status_t EFIAPI efi_set_variable(u16 *variable_name, efi_guid_t *vendor,
|
||||
u32 attributes, efi_uintn_t data_size,
|
||||
void *data)
|
||||
{
|
||||
char native_name[MAX_NATIVE_VAR_NAME + 1];
|
||||
efi_status_t ret = EFI_SUCCESS;
|
||||
char *val, *s;
|
||||
u32 attr;
|
||||
|
||||
EFI_ENTRY("\"%ls\" %pUl %x %lu %p", variable_name, vendor, attributes,
|
||||
EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
|
||||
data_size, data);
|
||||
|
||||
if (!variable_name || !vendor)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
config CMD_BOOTEFI_SELFTEST
|
||||
bool "Allow booting an EFI efi_selftest"
|
||||
depends on CMD_BOOTEFI
|
||||
imply FAT
|
||||
imply FAT_WRITE
|
||||
help
|
||||
This adds an EFI test application to U-Boot that can be executed
|
||||
with the 'bootefi selftest' command. It provides extended tests of
|
||||
|
|
|
@ -28,8 +28,13 @@ efi_selftest_textinput.o \
|
|||
efi_selftest_textoutput.o \
|
||||
efi_selftest_tpl.o \
|
||||
efi_selftest_util.o \
|
||||
efi_selftest_variables.o \
|
||||
efi_selftest_watchdog.o
|
||||
|
||||
ifeq ($(CONFIG_CMD_BOOTEFI_SELFTEST),y)
|
||||
obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
|
||||
obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest_block_device.o
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* This unit test checks the following protocol services:
|
||||
* ConnectController, DisconnectController,
|
||||
* InstallProtocol, UninstallProtocol,
|
||||
* InstallProtocol, ReinstallProtocol, UninstallProtocol,
|
||||
* OpenProtocol, CloseProtcol, OpenProtocolInformation
|
||||
*/
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
|||
|
||||
#define NUMBER_OF_CHILD_CONTROLLERS 4
|
||||
|
||||
static int interface1 = 1;
|
||||
static int interface2 = 2;
|
||||
static struct efi_boot_services *boottime;
|
||||
const efi_guid_t guid_driver_binding_protocol =
|
||||
EFI_DRIVER_BINDING_PROTOCOL_GUID;
|
||||
|
@ -271,7 +273,7 @@ static int setup(const efi_handle_t img_handle,
|
|||
/* Create controller handle */
|
||||
ret = boottime->install_protocol_interface(
|
||||
&handle_controller, &guid_controller,
|
||||
EFI_NATIVE_INTERFACE, NULL);
|
||||
EFI_NATIVE_INTERFACE, &interface1);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("InstallProtocolInterface failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
|
@ -299,6 +301,7 @@ static int setup(const efi_handle_t img_handle,
|
|||
* Disconnect and destroy the remaining child controllers.
|
||||
*
|
||||
* Connect a controller to a driver.
|
||||
* Reinstall the driver protocol on the controller.
|
||||
* Uninstall the driver protocol from the controller.
|
||||
*/
|
||||
static int execute(void)
|
||||
|
@ -361,9 +364,35 @@ static int execute(void)
|
|||
efi_st_error("Number of children %u != %u\n",
|
||||
(unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
|
||||
}
|
||||
/* Try to uninstall controller protocol using the wrong interface */
|
||||
ret = boottime->uninstall_protocol_interface(handle_controller,
|
||||
&guid_controller,
|
||||
&interface2);
|
||||
if (ret == EFI_SUCCESS) {
|
||||
efi_st_error(
|
||||
"Interface not checked when uninstalling protocol\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* Reinstall controller protocol */
|
||||
ret = boottime->reinstall_protocol_interface(handle_controller,
|
||||
&guid_controller,
|
||||
&interface1,
|
||||
&interface2);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("Failed to reinstall protocols\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* Check number of child controllers */
|
||||
ret = count_child_controllers(handle_controller, &guid_controller,
|
||||
&count);
|
||||
if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
|
||||
efi_st_error("Number of children %u != %u\n",
|
||||
(unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
|
||||
}
|
||||
/* Uninstall controller protocol */
|
||||
ret = boottime->uninstall_protocol_interface(handle_controller,
|
||||
&guid_controller, NULL);
|
||||
&guid_controller,
|
||||
&interface2);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("Failed to uninstall protocols\n");
|
||||
return EFI_ST_FAILURE;
|
||||
|
|
|
@ -335,7 +335,7 @@ static int execute(void)
|
|||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = boottime->uninstall_protocol_interface(handle1, &guid3,
|
||||
&interface1);
|
||||
&interface3);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("UninstallProtocolInterface failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
|
|
|
@ -23,6 +23,13 @@ static int execute(void)
|
|||
size_t background;
|
||||
size_t attrib;
|
||||
efi_status_t ret;
|
||||
s16 col;
|
||||
u16 cr[] = { 0x0d, 0x00 };
|
||||
u16 lf[] = { 0x0a, 0x00 };
|
||||
u16 brahmi[] = { /* 2 Brahmi letters */
|
||||
0xD804, 0xDC05,
|
||||
0xD804, 0xDC22,
|
||||
0};
|
||||
|
||||
/* SetAttribute */
|
||||
efi_st_printf("\nColor palette\n");
|
||||
|
@ -42,6 +49,77 @@ static int execute(void)
|
|||
efi_st_error("TestString failed for ANSI characters\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* OutputString */
|
||||
ret = con_out->output_string(con_out,
|
||||
L"Testing cursor column update\n");
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("OutputString failed for ANSI characters");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
col = con_out->mode->cursor_column;
|
||||
ret = con_out->output_string(con_out, lf);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("OutputString failed for line feed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (con_out->mode->cursor_column != col) {
|
||||
efi_st_error("Cursor column changed by line feed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = con_out->output_string(con_out, cr);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("OutputString failed for carriage return\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (con_out->mode->cursor_column) {
|
||||
efi_st_error("Cursor column not 0 at beginning of line\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = con_out->output_string(con_out, L"123");
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("OutputString failed for ANSI characters\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (con_out->mode->cursor_column != 3) {
|
||||
efi_st_error("Cursor column not incremented properly\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = con_out->output_string(con_out, L"\b");
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("OutputString failed for backspace\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (con_out->mode->cursor_column != 2) {
|
||||
efi_st_error("Cursor column not decremented properly\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = con_out->output_string(con_out, L"\b\b");
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("OutputString failed for backspace\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (con_out->mode->cursor_column) {
|
||||
efi_st_error("Cursor column not decremented properly\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = con_out->output_string(con_out, L"\b\b");
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_error("OutputString failed for backspace\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (con_out->mode->cursor_column) {
|
||||
efi_st_error("Cursor column decremented past zero\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
ret = con_out->output_string(con_out, brahmi);
|
||||
if (ret != EFI_ST_SUCCESS) {
|
||||
efi_st_todo("Unicode output not fully supported\n");
|
||||
} else if (con_out->mode->cursor_column != 2) {
|
||||
efi_st_printf("Unicode not handled properly\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
efi_st_printf("\n");
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
67
lib/efi_selftest/efi_selftest_unaligned.c
Normal file
67
lib/efi_selftest/efi_selftest_unaligned.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* efi_selftest_unaligned
|
||||
*
|
||||
* Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Test unaligned memory access on ARMv7.
|
||||
*/
|
||||
|
||||
#include <efi_selftest.h>
|
||||
|
||||
struct aligned_buffer {
|
||||
char a[8] __aligned(8);
|
||||
};
|
||||
|
||||
/*
|
||||
* Return an u32 at a give address.
|
||||
* If the address is not four byte aligned, an unaligned memory access
|
||||
* occurs.
|
||||
*
|
||||
* @addr: address to read
|
||||
* @return: value at the address
|
||||
*/
|
||||
static inline u32 deref(u32 *addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
asm(
|
||||
"ldr %[out], [%[in]]\n\t"
|
||||
: [out] "=r" (ret)
|
||||
: [in] "r" (addr)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute unit test.
|
||||
* An unaligned memory access is executed. The result is checked.
|
||||
*
|
||||
* @return: EFI_ST_SUCCESS for success
|
||||
*/
|
||||
static int execute(void)
|
||||
{
|
||||
struct aligned_buffer buf = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7},
|
||||
};
|
||||
void *v = &buf;
|
||||
u32 r = 0;
|
||||
|
||||
/* Read an unaligned address */
|
||||
r = deref(v + 1);
|
||||
|
||||
/* UEFI only supports low endian systems */
|
||||
if (r != 0x04030201) {
|
||||
efi_st_error("Unaligned access failed");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_UNIT_TEST(unaligned) = {
|
||||
.name = "unaligned memory access",
|
||||
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
|
||||
.execute = execute,
|
||||
};
|
196
lib/efi_selftest/efi_selftest_variables.c
Normal file
196
lib/efi_selftest/efi_selftest_variables.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* efi_selftest_variables
|
||||
*
|
||||
* Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||
*
|
||||
* This unit test checks the following protocol services:
|
||||
* ConnectController, DisconnectController,
|
||||
* InstallProtocol, ReinstallProtocol, UninstallProtocol,
|
||||
* OpenProtocol, CloseProtcol, OpenProtocolInformation
|
||||
*/
|
||||
|
||||
#include <efi_selftest.h>
|
||||
|
||||
#define EFI_ST_MAX_DATA_SIZE 16
|
||||
#define EFI_ST_MAX_VARNAME_SIZE 40
|
||||
|
||||
static struct efi_boot_services *boottime;
|
||||
static struct efi_runtime_services *runtime;
|
||||
static efi_guid_t guid_vendor0 =
|
||||
EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1,
|
||||
0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6);
|
||||
static efi_guid_t guid_vendor1 =
|
||||
EFI_GUID(0xff629290, 0x1fc1, 0xd73f,
|
||||
0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea);
|
||||
|
||||
/*
|
||||
* Setup unit test.
|
||||
*
|
||||
* @handle handle of the loaded image
|
||||
* @systable system table
|
||||
*/
|
||||
static int setup(const efi_handle_t img_handle,
|
||||
const struct efi_system_table *systable)
|
||||
{
|
||||
boottime = systable->boottime;
|
||||
runtime = systable->runtime;
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute unit test.
|
||||
*/
|
||||
static int execute(void)
|
||||
{
|
||||
efi_status_t ret;
|
||||
efi_uintn_t len;
|
||||
u32 attr;
|
||||
u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c,
|
||||
0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,};
|
||||
u8 data[EFI_ST_MAX_DATA_SIZE];
|
||||
u16 varname[EFI_ST_MAX_VARNAME_SIZE];
|
||||
int flag;
|
||||
efi_guid_t guid;
|
||||
u64 max_storage, rem_storage, max_size;
|
||||
|
||||
ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
&max_storage, &rem_storage,
|
||||
&max_size);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_todo("QueryVariableInfo failed\n");
|
||||
} else if (!max_storage || !rem_storage || !max_size) {
|
||||
efi_st_error("QueryVariableInfo: wrong info\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* Set variable 0 */
|
||||
ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
3, v + 4);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
data[3] = 0xff;
|
||||
len = 3;
|
||||
ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0,
|
||||
&attr, &len, data);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("GetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (efi_st_memcmp(data, v + 4, 3)) {
|
||||
efi_st_error("GetVariable returned wrong value\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (data[3] != 0xff) {
|
||||
efi_st_error("GetVariable wrote past the end of the buffer\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* Set variable 1 */
|
||||
ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
8, v);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = EFI_ST_MAX_DATA_SIZE;
|
||||
ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1,
|
||||
&attr, &len, data);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("GetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (len != 8) {
|
||||
efi_st_error("GetVariable returned wrong length %u\n",
|
||||
(unsigned int)len);
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (efi_st_memcmp(data, v, 8)) {
|
||||
efi_st_error("GetVariable returned wrong value\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* Append variable 1 */
|
||||
ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_APPEND_WRITE,
|
||||
7, v + 8);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = EFI_ST_MAX_DATA_SIZE;
|
||||
ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1,
|
||||
&attr, &len, data);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("GetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
if (len != 15)
|
||||
efi_st_todo("GetVariable returned wrong length %u\n",
|
||||
(unsigned int)len);
|
||||
if (efi_st_memcmp(data, v, len))
|
||||
efi_st_todo("GetVariable returned wrong value\n");
|
||||
/* Enumerate variables */
|
||||
boottime->set_mem(&guid, 16, 0);
|
||||
*varname = 0;
|
||||
flag = 0;
|
||||
for (;;) {
|
||||
len = EFI_ST_MAX_VARNAME_SIZE;
|
||||
ret = runtime->get_next_variable_name(&len, varname, &guid);
|
||||
if (ret == EFI_NOT_FOUND)
|
||||
break;
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_todo("GetNextVariableName failed\n");
|
||||
break;
|
||||
}
|
||||
if (!efi_st_memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) &&
|
||||
!efi_st_strcmp_16_8(varname, "efi_st_var0"))
|
||||
flag |= 2;
|
||||
if (!efi_st_memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) &&
|
||||
!efi_st_strcmp_16_8(varname, "efi_st_var1"))
|
||||
flag |= 2;
|
||||
}
|
||||
if (flag != 3)
|
||||
efi_st_todo(
|
||||
"GetNextVariableName did not return all variables\n");
|
||||
/* Delete variable 1 */
|
||||
ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1,
|
||||
0, 0, NULL);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = EFI_ST_MAX_DATA_SIZE;
|
||||
ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1,
|
||||
&attr, &len, data);
|
||||
if (ret != EFI_NOT_FOUND) {
|
||||
efi_st_error("Variable was not deleted\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
/* Delete variable 0 */
|
||||
ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0,
|
||||
0, 0, NULL);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_error("SetVariable failed\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
len = EFI_ST_MAX_DATA_SIZE;
|
||||
ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0,
|
||||
&attr, &len, data);
|
||||
if (ret != EFI_NOT_FOUND) {
|
||||
efi_st_error("Variable was not deleted\n");
|
||||
return EFI_ST_FAILURE;
|
||||
}
|
||||
|
||||
return EFI_ST_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_UNIT_TEST(variables) = {
|
||||
.name = "variables",
|
||||
.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
|
||||
.setup = setup,
|
||||
.execute = execute,
|
||||
};
|
Loading…
Add table
Reference in a new issue