From mboxrd@z Thu Jan 1 00:00:00 1970 From: Leif Lindholm Date: Thu, 21 Jan 2016 17:20:18 +0000 Subject: [U-Boot] [PATCH 06/14] efi_loader: Add runtime services In-Reply-To: <1452834380-164453-7-git-send-email-agraf@suse.de> References: <1452834380-164453-1-git-send-email-agraf@suse.de> <1452834380-164453-7-git-send-email-agraf@suse.de> Message-ID: <20160121172018.GD25034@bivouac.eciton.net> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On Fri, Jan 15, 2016 at 06:06:12AM +0100, Alexander Graf wrote: > After booting has finished, EFI allows firmware to still interact with the OS > using the "runtime services". These callbacks live in a separate address space, > since they are available long after U-Boot has been overwritten by the OS. > > This patch adds enough framework for arbitrary code inside of U-Boot to become > a runtime service with the right section attributes set. For now, we don't make > use of it yet though. > > We could maybe in the future map U-boot environment variables to EFI variables > here. > > Signed-off-by: Alexander Graf Just a couple of return value issues: > --- > > v1 -> v2: > > - Fix runtime service sections > - Add runtime detach > - Enable runtime relocations > - Add get_time > - Fix relocation > - Fix 32bit > - Add am335x support > - Move section definition to header > - Add systab to runtime section > - Add self-relocation hook table > - Fix self-relocation > - Relocate efi_runtime section early during bootup > - Fix return values for a number of callbacks to be more UEFI compliant > - Move to GPLv2+ > --- > arch/arm/config.mk | 4 + > arch/arm/cpu/armv8/u-boot.lds | 16 +++ > arch/arm/cpu/u-boot.lds | 30 +++++ > arch/arm/lib/sections.c | 4 + > board/ti/am335x/u-boot.lds | 30 +++++ > common/board_r.c | 4 + > include/efi_loader.h | 10 ++ > lib/efi_loader/efi_boottime.c | 6 +- > lib/efi_loader/efi_runtime.c | 300 ++++++++++++++++++++++++++++++++++++++++++ > 9 files changed, 401 insertions(+), 3 deletions(-) > create mode 100644 lib/efi_loader/efi_runtime.c > ... > diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c > new file mode 100644 > index 0000000..b7aa1e9 > --- /dev/null > +++ b/lib/efi_loader/efi_runtime.c > @@ -0,0 +1,300 @@ > +/* > + * EFI application runtime services > + * > + * Copyright (c) 2016 Alexander Graf > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +/* For manual relocation support */ > +DECLARE_GLOBAL_DATA_PTR; > + > +static efi_status_t EFI_RUNTIME_TEXT efi_unimplemented(void); > +static efi_status_t EFI_RUNTIME_TEXT efi_device_error(void); > +static efi_status_t EFI_RUNTIME_TEXT efi_invalid_parameter(void); > + > +#if defined(CONFIG_ARM64) > +#define R_RELATIVE 1027 > +#define R_MASK 0xffffffffULL > +#define IS_RELA 1 > +#elif defined(CONFIG_ARM) > +#define R_RELATIVE 23 > +#define R_MASK 0xffULL > +#else > +#error Need to add relocation awareness > +#endif > + > +struct elf_rel { > + ulong *offset; > + ulong info; > +}; > + > +struct elf_rela { > + ulong *offset; > + ulong info; > + long addend; > +}; > + > +/* > + * EFI Runtime code lives in 2 stages. In the first stage, U-Boot and an EFI > + * payload are running concurrently at the same time. In this mode, we can > + * handle a good number of runtime callbacks > + */ > + > +static void efi_reset_system(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); > + > + switch (reset_type) { > + case EFI_RESET_COLD: > + case EFI_RESET_WARM: > + do_reset(NULL, 0, 0, NULL); > + break; > + case EFI_RESET_SHUTDOWN: > + /* We don't have anything to map this to */ > + break; > + } > + > + EFI_EXIT(EFI_SUCCESS); > +} > + > +static efi_status_t efi_get_time(struct efi_time *time, > + struct efi_time_cap *capabilities) > +{ > +#ifdef CONFIG_CMD_DATE > + > + struct rtc_time tm; > + int r; > +#ifdef CONFIG_DM_RTC > + struct udevice *dev; > +#endif > + > + EFI_ENTRY("%p %p", time, capabilities); > + > +#ifdef CONFIG_DM_RTC > + r = uclass_get_device(UCLASS_RTC, 0, &dev); > + if (r) > + return EFI_EXIT(EFI_UNSUPPORTED); EFI_DEVICE_ERROR? > +#endif > + > +#ifdef CONFIG_DM_RTC > + r = dm_rtc_get(dev, &tm); > +#else > + r = rtc_get(&tm); > +#endif > + if (r) > + return EFI_EXIT(EFI_UNSUPPORTED); EFI_DEVICE_ERROR? > + > + memset(time, 0, sizeof(*time)); > + time->year = tm.tm_year; > + time->month = tm.tm_mon; > + time->day = tm.tm_mday; > + time->hour = tm.tm_hour; > + time->minute = tm.tm_min; > + time->daylight = tm.tm_isdst; > + > + return EFI_EXIT(EFI_SUCCESS); > + > +#else /* CONFIG_CMD_DATE */ > + > + return EFI_DEVICE_ERROR; > + > +#endif /* CONFIG_CMD_DATE */ > +}