$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
$(call if_changed_rule,cc_o_c)
- lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o
+ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
+ screen_info.o efi-stub-entry.o
lib-$(CONFIG_ARM) += arm32-stub.o
- lib-$(CONFIG_ARM64) += arm64-stub.o smbios.o
-lib-$(CONFIG_ARM64) += arm64.o arm64-stub.o arm64-entry.o
++lib-$(CONFIG_ARM64) += arm64.o arm64-stub.o arm64-entry.o smbios.o
lib-$(CONFIG_X86) += x86-stub.o
- lib-$(CONFIG_RISCV) += riscv-stub.o
- lib-$(CONFIG_LOONGARCH) += loongarch-stub.o
+ lib-$(CONFIG_RISCV) += riscv.o riscv-stub.o
+ lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
--- /dev/null
- if (VA_BITS_MIN >= 48)
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+ * Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org>
+ *
+ * This file implements the EFI boot stub for the arm64 kernel.
+ * Adapted from ARM version by Mark Salter <msalter@redhat.com>
+ */
+
+
+ #include <linux/efi.h>
+ #include <asm/efi.h>
+ #include <asm/memory.h>
+ #include <asm/sysreg.h>
+
+ #include "efistub.h"
+
++static bool system_needs_vamap(void)
++{
++ const u8 *type1_family = efi_get_smbios_string(1, family);
++
++ /*
++ * Ampere Altra machines crash in SetTime() if SetVirtualAddressMap()
++ * has not been called prior.
++ */
++ if (!type1_family || strcmp(type1_family, "Altra"))
++ return false;
++
++ efi_warn("Working around broken SetVirtualAddressMap()\n");
++ return true;
++}
++
+ efi_status_t check_platform_features(void)
+ {
+ u64 tg;
+
+ /*
+ * If we have 48 bits of VA space for TTBR0 mappings, we can map the
+ * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
+ * unnecessary.
+ */
++ if (VA_BITS_MIN >= 48 && !system_needs_vamap())
+ efi_novamap = true;
+
+ /* UEFI mandates support for 4 KB granularity, no need to check */
+ if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
+ return EFI_SUCCESS;
+
+ tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf;
+ if (tg < ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX) {
+ if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+ efi_err("This 64 KB granular kernel is not supported by your CPU\n");
+ else
+ efi_err("This 16 KB granular kernel is not supported by your CPU\n");
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+ }
+
+ void efi_cache_sync_image(unsigned long image_base,
+ unsigned long alloc_size,
+ unsigned long code_size)
+ {
+ u32 ctr = read_cpuid_effective_cachetype();
+ u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
+ CTR_EL0_DminLine_SHIFT);
+
+ do {
+ asm("dc civac, %0" :: "r"(image_base));
+ image_base += lsize;
+ alloc_size -= lsize;
+ } while (alloc_size >= lsize);
+
+ asm("ic ialluis");
+ dsb(ish);
+ isb();
+ }
void efi_retrieve_tpm2_eventlog(void);
+ struct screen_info *alloc_screen_info(void);
+ void free_screen_info(struct screen_info *si);
+
+ void efi_cache_sync_image(unsigned long image_base,
+ unsigned long alloc_size,
+ unsigned long code_size);
+
+struct efi_smbios_record {
+ u8 type;
+ u8 length;
+ u16 handle;
+};
+
+struct efi_smbios_type1_record {
+ struct efi_smbios_record header;
+
+ u8 manufacturer;
+ u8 product_name;
+ u8 version;
+ u8 serial_number;
+ efi_guid_t uuid;
+ u8 wakeup_type;
+ u8 sku_number;
+ u8 family;
+};
+
+#define efi_get_smbios_string(__type, __name) ({ \
+ int size = sizeof(struct efi_smbios_type ## __type ## _record); \
+ int off = offsetof(struct efi_smbios_type ## __type ## _record, \
+ __name); \
+ __efi_get_smbios_string(__type, off, size); \
+})
+
+const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
+
#endif