diff options
Diffstat (limited to 'lib')
79 files changed, 1367 insertions, 489 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 868de3bf3b8..af5c38afd98 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -162,7 +162,7 @@ config LIB_RAND bool "Pseudo-random library support" config LIB_HW_RAND - bool "HW Engine for random libray support" + bool "HW Engine for random library support" endchoice @@ -363,7 +363,22 @@ config SHA_PROG_HW_ACCEL is performed in hardware. config MD5 - bool + bool "Support MD5 algorithm" + help + This option enables MD5 support. MD5 is an algorithm designed + in 1991 that produces a 16-byte digest (or checksum) from its input + data. It has a number of vulnerabilities which preclude its use in + security applications, but it can be useful for providing a quick + checksum of a block of data. + +config SPL_MD5 + bool "Support MD5 algorithm in SPL" + help + This option enables MD5 support in SPL. MD5 is an algorithm designed + in 1991 that produces a 16-byte digest (or checksum) from its input + data. It has a number of vulnerabilities which preclude its use in + security applications, but it can be useful for providing a quick + checksum of a block of data. config CRC32C bool @@ -409,6 +424,10 @@ config GZIP help This enables support for GZIP compression algorithm. +config GZIP_COMPRESSED + bool + select ZLIB + config BZIP2 bool "Enable bzip2 decompression support" help @@ -429,7 +448,7 @@ config ZSTD config SPL_LZ4 bool "Enable LZ4 decompression support in SPL" help - This enables support for tge LZ4 decompression algorithm in SPL. LZ4 + This enables support for the LZ4 decompression algorithm in SPL. LZ4 is a lossless data compression algorithm that is focused on fast compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes. @@ -437,7 +456,7 @@ config SPL_LZ4 config SPL_LZMA bool "Enable LZMA decompression support for SPL build" help - This enables support for LZMA compression altorithm for SPL boot. + This enables support for LZMA compression algorithm for SPL boot. config SPL_LZO bool "Enable LZO decompression support in SPL" diff --git a/lib/Makefile b/lib/Makefile index c6f862b0c22..6e688afa686 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-y += ldiv.o -obj-$(CONFIG_MD5) += md5.o obj-$(CONFIG_XXHASH) += xxhash.o obj-y += net_utils.o obj-$(CONFIG_PHYSMEM) += physmem.o @@ -59,6 +58,7 @@ obj-$(CONFIG_TPM_V2) += tpm-v2.o endif obj-$(CONFIG_$(SPL_)ACPIGEN) += acpi/ +obj-$(CONFIG_$(SPL_)MD5) += md5.o obj-$(CONFIG_$(SPL_)RSA) += rsa/ obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA256) += sha256.o diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 4633dcb9488..431776666e2 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -6,12 +6,15 @@ */ #include <common.h> -#include <acpi/acpi_table.h> #include <dm.h> #include <cpu.h> +#include <log.h> +#include <mapmem.h> +#include <tables_csum.h> +#include <version.h> +#include <acpi/acpi_table.h> +#include <dm/acpi.h> -/* Temporary change to ensure bisectability */ -#ifndef CONFIG_SANDBOX int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags) { struct acpi_table_header *header = &dmar->header; @@ -37,7 +40,6 @@ int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags) return 0; } -#endif int acpi_get_table_revision(enum acpi_tables table) { @@ -91,3 +93,173 @@ int acpi_get_table_revision(enum acpi_tables table) return -EINVAL; } } + +void acpi_fill_header(struct acpi_table_header *header, char *signature) +{ + memcpy(header->signature, signature, 4); + memcpy(header->oem_id, OEM_ID, 6); + memcpy(header->oem_table_id, OEM_TABLE_ID, 8); + header->oem_revision = U_BOOT_BUILD_DATE; + memcpy(header->aslc_id, ASLC_ID, 4); +} + +void acpi_align(struct acpi_ctx *ctx) +{ + ctx->current = (void *)ALIGN((ulong)ctx->current, 16); +} + +void acpi_align64(struct acpi_ctx *ctx) +{ + ctx->current = (void *)ALIGN((ulong)ctx->current, 64); +} + +void acpi_inc(struct acpi_ctx *ctx, uint amount) +{ + ctx->current += amount; +} + +void acpi_inc_align(struct acpi_ctx *ctx, uint amount) +{ + ctx->current += amount; + acpi_align(ctx); +} + +/** + * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length + * and checksum. + */ +int acpi_add_table(struct acpi_ctx *ctx, void *table) +{ + int i, entries_num; + struct acpi_rsdt *rsdt; + struct acpi_xsdt *xsdt; + + /* The RSDT is mandatory while the XSDT is not */ + rsdt = ctx->rsdt; + + /* This should always be MAX_ACPI_TABLES */ + entries_num = ARRAY_SIZE(rsdt->entry); + + for (i = 0; i < entries_num; i++) { + if (rsdt->entry[i] == 0) + break; + } + + if (i >= entries_num) { + log_err("ACPI: Error: too many tables\n"); + return -E2BIG; + } + + /* Add table to the RSDT */ + rsdt->entry[i] = map_to_sysmem(table); + + /* Fix RSDT length or the kernel will assume invalid entries */ + rsdt->header.length = sizeof(struct acpi_table_header) + + (sizeof(u32) * (i + 1)); + + /* Re-calculate checksum */ + rsdt->header.checksum = 0; + rsdt->header.checksum = table_compute_checksum((u8 *)rsdt, + rsdt->header.length); + + /* + * And now the same thing for the XSDT. We use the same index as for + * now we want the XSDT and RSDT to always be in sync in U-Boot + */ + xsdt = ctx->xsdt; + + /* Add table to the XSDT */ + xsdt->entry[i] = map_to_sysmem(table); + + /* Fix XSDT length */ + xsdt->header.length = sizeof(struct acpi_table_header) + + (sizeof(u64) * (i + 1)); + + /* Re-calculate checksum */ + xsdt->header.checksum = 0; + xsdt->header.checksum = table_compute_checksum((u8 *)xsdt, + xsdt->header.length); + + return 0; +} + +static void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, + struct acpi_xsdt *xsdt) +{ + memset(rsdp, 0, sizeof(struct acpi_rsdp)); + + memcpy(rsdp->signature, RSDP_SIG, 8); + memcpy(rsdp->oem_id, OEM_ID, 6); + + rsdp->length = sizeof(struct acpi_rsdp); + rsdp->rsdt_address = map_to_sysmem(rsdt); + + rsdp->xsdt_address = map_to_sysmem(xsdt); + rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; + + /* Calculate checksums */ + rsdp->checksum = table_compute_checksum(rsdp, 20); + rsdp->ext_checksum = table_compute_checksum(rsdp, + sizeof(struct acpi_rsdp)); +} + +static void acpi_write_rsdt(struct acpi_rsdt *rsdt) +{ + struct acpi_table_header *header = &rsdt->header; + + /* Fill out header fields */ + acpi_fill_header(header, "RSDT"); + header->length = sizeof(struct acpi_rsdt); + header->revision = 1; + + /* Entries are filled in later, we come with an empty set */ + + /* Fix checksum */ + header->checksum = table_compute_checksum(rsdt, + sizeof(struct acpi_rsdt)); +} + +static void acpi_write_xsdt(struct acpi_xsdt *xsdt) +{ + struct acpi_table_header *header = &xsdt->header; + + /* Fill out header fields */ + acpi_fill_header(header, "XSDT"); + header->length = sizeof(struct acpi_xsdt); + header->revision = 1; + + /* Entries are filled in later, we come with an empty set */ + + /* Fix checksum */ + header->checksum = table_compute_checksum(xsdt, + sizeof(struct acpi_xsdt)); +} + +void acpi_setup_base_tables(struct acpi_ctx *ctx, void *start) +{ + ctx->current = start; + + /* Align ACPI tables to 16 byte */ + acpi_align(ctx); + gd->arch.acpi_start = map_to_sysmem(ctx->current); + + /* We need at least an RSDP and an RSDT Table */ + ctx->rsdp = ctx->current; + acpi_inc_align(ctx, sizeof(struct acpi_rsdp)); + ctx->rsdt = ctx->current; + acpi_inc_align(ctx, sizeof(struct acpi_rsdt)); + ctx->xsdt = ctx->current; + acpi_inc_align(ctx, sizeof(struct acpi_xsdt)); + + /* clear all table memory */ + memset((void *)start, '\0', ctx->current - start); + + acpi_write_rsdp(ctx->rsdp, ctx->rsdt, ctx->xsdt); + acpi_write_rsdt(ctx->rsdt); + acpi_write_xsdt(ctx->xsdt); + /* + * Per ACPI spec, the FACS table address must be aligned to a 64 byte + * boundary (Windows checks this, but Linux does not). + */ + acpi_align64(ctx); +} diff --git a/lib/aes.c b/lib/aes.c index ce53c9f1f37..c998aecb3c7 100644 --- a/lib/aes.c +++ b/lib/aes.c @@ -23,6 +23,7 @@ #ifndef USE_HOSTCC #include <common.h> +#include <log.h> #else #include <string.h> #endif diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c index 26175132f32..b17651ed63d 100644 --- a/lib/asm-offsets.c +++ b/lib/asm-offsets.c @@ -12,6 +12,7 @@ */ #include <common.h> +#include <asm-offsets.h> #include <linux/kbuild.h> diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index db222625dd0..bcb0390eb41 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -6,6 +6,7 @@ */ #ifdef __UBOOT__ +#include <log.h> #include <linux/compat.h> #else #include <linux/export.h> diff --git a/lib/bch.c b/lib/bch.c index 8945d8d4cf2..de66b1acba5 100644 --- a/lib/bch.c +++ b/lib/bch.c @@ -55,6 +55,7 @@ #ifndef USE_HOSTCC #include <common.h> +#include <log.h> #include <malloc.h> #include <ubi_uboot.h> #include <dm/devres.h> diff --git a/lib/binman.c b/lib/binman.c index 6cf6dcfdad6..fd7de24bd23 100644 --- a/lib/binman.c +++ b/lib/binman.c @@ -9,6 +9,7 @@ #include <common.h> #include <binman.h> #include <dm.h> +#include <log.h> #include <malloc.h> struct binman_info { diff --git a/lib/bzip2/bzlib_blocksort.c b/lib/bzip2/bzlib_blocksort.c index 27855215022..36cf8436592 100644 --- a/lib/bzip2/bzlib_blocksort.c +++ b/lib/bzip2/bzlib_blocksort.c @@ -60,6 +60,7 @@ --*/ #include "bzlib_private.h" +#include <log.h> /*---------------------------------------------*/ /*--- Fallback O(N log(N)^2) sorting ---*/ diff --git a/lib/charset.c b/lib/charset.c index 1c6a7f693de..a28034ee1f1 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -379,6 +379,11 @@ size_t u16_strnlen(const u16 *in, size_t count) return i; } +size_t u16_strsize(const void *in) +{ + return (u16_strlen(in) + 1) * sizeof(u16); +} + u16 *u16_strcpy(u16 *dest, const u16 *src) { u16 *tmp = dest; diff --git a/lib/circbuf.c b/lib/circbuf.c index 071e4fb8a6a..fa79c148dae 100644 --- a/lib/circbuf.c +++ b/lib/circbuf.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <log.h> #include <malloc.h> #include <circbuf.h> diff --git a/lib/crypto/asymmetric_type.c b/lib/crypto/asymmetric_type.c index 7aa55092ac7..1d0532d0f2e 100644 --- a/lib/crypto/asymmetric_type.c +++ b/lib/crypto/asymmetric_type.c @@ -7,12 +7,14 @@ * Written by David Howells (dhowells@redhat.com) */ #ifndef __UBOOT__ +#include <log.h> #include <dm/devres.h> #include <keys/asymmetric-subtype.h> #include <keys/asymmetric-parser.h> #endif #include <crypto/public_key.h> #ifdef __UBOOT__ +#include <linux/bug.h> #include <linux/compat.h> #include <linux/ctype.h> #include <linux/err.h> diff --git a/lib/crypto/pkcs7_parser.c b/lib/crypto/pkcs7_parser.c index f5dda1179f8..0b85fe8286c 100644 --- a/lib/crypto/pkcs7_parser.c +++ b/lib/crypto/pkcs7_parser.c @@ -7,6 +7,7 @@ #define pr_fmt(fmt) "PKCS7: "fmt #ifdef __UBOOT__ +#include <log.h> #include <dm/devres.h> #include <linux/bitops.h> #include <linux/compat.h> @@ -20,7 +21,11 @@ #include <linux/err.h> #include <linux/oid_registry.h> #include <crypto/public_key.h> +#ifdef __UBOOT__ +#include <crypto/pkcs7_parser.h> +#else #include "pkcs7_parser.h" +#endif #include "pkcs7.asn1.h" MODULE_DESCRIPTION("PKCS#7 parser"); diff --git a/lib/crypto/pkcs7_parser.h b/lib/crypto/pkcs7_parser.h deleted file mode 100644 index 6565fdc2d4c..00000000000 --- a/lib/crypto/pkcs7_parser.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* PKCS#7 crypto data parser internal definitions - * - * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - */ - -#include <linux/oid_registry.h> -#include <crypto/pkcs7.h> -#include "x509_parser.h" - -#define kenter(FMT, ...) \ - pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) -#define kleave(FMT, ...) \ - pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) - -struct pkcs7_signed_info { - struct pkcs7_signed_info *next; - struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ - unsigned index; - bool unsupported_crypto; /* T if not usable due to missing crypto */ - bool blacklisted; - - /* Message digest - the digest of the Content Data (or NULL) */ - const void *msgdigest; - unsigned msgdigest_len; - - /* Authenticated Attribute data (or NULL) */ - unsigned authattrs_len; - const void *authattrs; - unsigned long aa_set; -#define sinfo_has_content_type 0 -#define sinfo_has_signing_time 1 -#define sinfo_has_message_digest 2 -#define sinfo_has_smime_caps 3 -#define sinfo_has_ms_opus_info 4 -#define sinfo_has_ms_statement_type 5 - time64_t signing_time; - - /* Message signature. - * - * This contains the generated digest of _either_ the Content Data or - * the Authenticated Attributes [RFC2315 9.3]. If the latter, one of - * the attributes contains the digest of the the Content Data within - * it. - * - * THis also contains the issuing cert serial number and issuer's name - * [PKCS#7 or CMS ver 1] or issuing cert's SKID [CMS ver 3]. - */ - struct public_key_signature *sig; -}; - -struct pkcs7_message { - struct x509_certificate *certs; /* Certificate list */ - struct x509_certificate *crl; /* Revocation list */ - struct pkcs7_signed_info *signed_infos; - u8 version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */ - bool have_authattrs; /* T if have authattrs */ - - /* Content Data (or NULL) */ - enum OID data_type; /* Type of Data */ - size_t data_len; /* Length of Data */ - size_t data_hdrlen; /* Length of Data ASN.1 header */ - const void *data; /* Content Data (or 0) */ -}; diff --git a/lib/crypto/public_key.c b/lib/crypto/public_key.c index 8b4821767aa..e12ebbb3d0c 100644 --- a/lib/crypto/public_key.c +++ b/lib/crypto/public_key.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) "PKEY: "fmt #ifdef __UBOOT__ #include <dm/devres.h> +#include <linux/bug.h> #include <linux/compat.h> #include <linux/err.h> #else diff --git a/lib/crypto/x509_cert_parser.c b/lib/crypto/x509_cert_parser.c index 4e41cffd230..5f984b9dfda 100644 --- a/lib/crypto/x509_cert_parser.c +++ b/lib/crypto/x509_cert_parser.c @@ -6,6 +6,7 @@ */ #define pr_fmt(fmt) "X.509: "fmt +#include <log.h> #include <dm/devres.h> #include <linux/kernel.h> #ifndef __UBOOT__ @@ -18,7 +19,11 @@ #include <linux/string.h> #endif #include <crypto/public_key.h> +#ifdef __UBOOT__ +#include <crypto/x509_parser.h> +#else #include "x509_parser.h" +#endif #include "x509.asn1.h" #include "x509_akid.asn1.h" diff --git a/lib/crypto/x509_parser.h b/lib/crypto/x509_parser.h deleted file mode 100644 index c233f136fb3..00000000000 --- a/lib/crypto/x509_parser.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* X.509 certificate parser internal definitions - * - * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - */ - -#include <linux/time.h> -#include <crypto/public_key.h> -#include <keys/asymmetric-type.h> - -struct x509_certificate { - struct x509_certificate *next; - struct x509_certificate *signer; /* Certificate that signed this one */ - struct public_key *pub; /* Public key details */ - struct public_key_signature *sig; /* Signature parameters */ - char *issuer; /* Name of certificate issuer */ - char *subject; /* Name of certificate subject */ - struct asymmetric_key_id *id; /* Issuer + Serial number */ - struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */ - time64_t valid_from; - time64_t valid_to; - const void *tbs; /* Signed data */ - unsigned tbs_size; /* Size of signed data */ - unsigned raw_sig_size; /* Size of sigature */ - const void *raw_sig; /* Signature data */ - const void *raw_serial; /* Raw serial number in ASN.1 */ - unsigned raw_serial_size; - unsigned raw_issuer_size; - const void *raw_issuer; /* Raw issuer name in ASN.1 */ - const void *raw_subject; /* Raw subject name in ASN.1 */ - unsigned raw_subject_size; - unsigned raw_skid_size; - const void *raw_skid; /* Raw subjectKeyId in ASN.1 */ - unsigned index; - bool seen; /* Infinite recursion prevention */ - bool verified; - bool self_signed; /* T if self-signed (check unsupported_sig too) */ - bool unsupported_key; /* T if key uses unsupported crypto */ - bool unsupported_sig; /* T if signature uses unsupported crypto */ - bool blacklisted; -}; - -/* - * x509_cert_parser.c - */ -extern void x509_free_certificate(struct x509_certificate *cert); -extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); -extern int x509_decode_time(time64_t *_t, size_t hdrlen, - unsigned char tag, - const unsigned char *value, size_t vlen); - -/* - * x509_public_key.c - */ -extern int x509_get_sig_params(struct x509_certificate *cert); -extern int x509_check_for_self_signed(struct x509_certificate *cert); diff --git a/lib/crypto/x509_public_key.c b/lib/crypto/x509_public_key.c index 676c0df1741..571af9a0adf 100644 --- a/lib/crypto/x509_public_key.c +++ b/lib/crypto/x509_public_key.c @@ -16,15 +16,17 @@ #include <linux/module.h> #endif #include <linux/kernel.h> -#ifndef __UBOOT__ +#ifdef __UBOOT__ +#include <crypto/x509_parser.h> +#else #include <linux/slab.h> #include <keys/asymmetric-subtype.h> #include <keys/asymmetric-parser.h> #include <keys/system_keyring.h> #include <crypto/hash.h> #include "asymmetric_keys.h" -#endif #include "x509_parser.h" +#endif /* * Set up the signature parameters in an X.509 certificate. This involves diff --git a/lib/dhry/cmd_dhry.c b/lib/dhry/cmd_dhry.c index 29504833efb..d55ab54df97 100644 --- a/lib/dhry/cmd_dhry.c +++ b/lib/dhry/cmd_dhry.c @@ -8,7 +8,8 @@ #include <div64.h> #include "dhry.h" -static int do_dhry(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_dhry(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) { ulong start, duration, vax_mips; u64 dhry_per_sec; diff --git a/lib/div64.c b/lib/div64.c index 62933c92c4f..779d7521f69 100644 --- a/lib/div64.c +++ b/lib/div64.c @@ -17,6 +17,7 @@ * or by defining a preprocessor macro in arch/include/asm/div64.h. */ +#include <linux/bitops.h> #include <linux/compat.h> #include <linux/kernel.h> #include <linux/math64.h> diff --git a/lib/efi/efi_app.c b/lib/efi/efi_app.c index 7c64077d42e..b7e19c34750 100644 --- a/lib/efi/efi_app.c +++ b/lib/efi/efi_app.c @@ -13,6 +13,7 @@ #include <debug_uart.h> #include <dm.h> #include <errno.h> +#include <init.h> #include <malloc.h> #include <linux/err.h> #include <linux/types.h> diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 33e66fcad2e..e7d8745ad85 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -28,6 +28,8 @@ * iPXE uses the simple file protocol to load Grub or the Linux Kernel. */ +#include <common.h> +#include <blk.h> #include <efi_driver.h> #include <malloc.h> #include <dm/device-internal.h> diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index f8badadf660..04e4e457344 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -18,6 +18,7 @@ */ #include <efi_driver.h> +#include <log.h> #include <malloc.h> /** diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 1cfa24ffcf7..aad37b71550 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -164,4 +164,13 @@ config EFI_SECURE_BOOT it is signed with a trusted key. To do that, you need to install, at least, PK, KEK and db. +config EFI_MM_COMM_TEE + bool "UEFI variables storage service via OP-TEE" + depends on OPTEE + default n + help + If OP-TEE is present and running StandAloneMM, dispatch all UEFI variable + related operations to that. The application will verify, authenticate and + store the variables on an RPMB. + endif diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index eff3c25ec30..57c7e66ea0e 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -17,6 +17,7 @@ CFLAGS_REMOVE_helloworld.o := $(CFLAGS_NON_EFI) ifneq ($(CONFIG_CMD_BOOTEFI_HELLO_COMPILE),) always += helloworld.efi +targets += helloworld.o endif obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o @@ -34,7 +35,11 @@ obj-y += efi_root_node.o obj-y += efi_runtime.o obj-y += efi_setup.o obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o +ifeq ($(CONFIG_EFI_MM_COMM_TEE),y) +obj-y += efi_variable_tee.o +else obj-y += efi_variable.o +endif obj-y += efi_watchdog.o obj-$(CONFIG_LCD) += efi_gop.o obj-$(CONFIG_DM_VIDEO) += efi_gop.o diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c index 9ae9c25c51e..585b2d2b636 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -7,6 +7,7 @@ #include <common.h> #include <efi_loader.h> +#include <log.h> #include <acpi/acpi_table.h> static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID; diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 2ea21448f03..e144b3e7f43 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -7,6 +7,7 @@ #include <common.h> #include <charset.h> +#include <log.h> #include <malloc.h> #include <efi_loader.h> #include <asm/unaligned.h> @@ -35,24 +36,50 @@ static const struct efi_runtime_services *rs; * * @lo: pointer to target * @data: serialized data + * @size: size of the load option, on return size of the optional data + * Return: status code */ -void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data) +efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data, + efi_uintn_t *size) { + efi_uintn_t len; + + len = sizeof(u32); + if (*size < len + 2 * sizeof(u16)) + return EFI_INVALID_PARAMETER; lo->attributes = get_unaligned_le32(data); - data += sizeof(u32); + data += len; + *size -= len; + len = sizeof(u16); lo->file_path_length = get_unaligned_le16(data); - data += sizeof(u16); + data += len; + *size -= len; - /* FIXME */ lo->label = (u16 *)data; - data += (u16_strlen(lo->label) + 1) * sizeof(u16); - - /* FIXME */ + len = u16_strnlen(lo->label, *size / sizeof(u16) - 1); + if (lo->label[len]) + return EFI_INVALID_PARAMETER; + len = (len + 1) * sizeof(u16); + if (*size < len) + return EFI_INVALID_PARAMETER; + data += len; + *size -= len; + + len = lo->file_path_length; + if (*size < len) + return EFI_INVALID_PARAMETER; lo->file_path = (struct efi_device_path *)data; - data += lo->file_path_length; + /* + * TODO: validate device path. There should be an end node within + * the indicated file_path_length. + */ + data += len; + *size -= len; lo->optional_data = data; + + return EFI_SUCCESS; } /** @@ -167,7 +194,11 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) if (!load_option) return EFI_LOAD_ERROR; - efi_deserialize_load_option(&lo, load_option); + ret = efi_deserialize_load_option(&lo, load_option, &size); + if (ret != EFI_SUCCESS) { + log_warning("Invalid load option for %ls\n", varname); + goto error; + } if (lo.attributes & LOAD_OPTION_ACTIVE) { u32 attributes; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index a3f11eaf622..1591ad83007 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -9,6 +9,7 @@ #include <div64.h> #include <efi_loader.h> #include <irq_func.h> +#include <log.h> #include <malloc.h> #include <time.h> #include <linux/libfdt_env.h> @@ -48,7 +49,7 @@ static efi_handle_t current_image; * restriction so we need to manually swap its and our view of that register on * EFI callback entry/exit. */ -static volatile void *efi_gd, *app_gd; +static volatile gd_t *efi_gd, *app_gd; #endif /* 1 if inside U-Boot code, 0 if inside EFI payload code */ @@ -88,7 +89,7 @@ int __efi_entry_check(void) #ifdef CONFIG_ARM assert(efi_gd); app_gd = gd; - gd = efi_gd; + set_gd(efi_gd); #endif return ret; } @@ -98,7 +99,7 @@ int __efi_exit_check(void) { int ret = --entry_count == 0; #ifdef CONFIG_ARM - gd = app_gd; + set_gd(app_gd); #endif return ret; } @@ -122,7 +123,7 @@ void efi_restore_gd(void) /* Only restore if we're already in EFI context */ if (!efi_gd) return; - gd = efi_gd; + set_gd(efi_gd); #endif } @@ -2919,7 +2920,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, * otherwise __efi_entry_check() will put the wrong value into * app_gd. */ - gd = app_gd; + set_gd(app_gd); #endif /* * To get ready to call EFI_EXIT below we have to execute the diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 73f1fe75a83..7ae14f34239 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -8,6 +8,8 @@ #include <common.h> #include <blk.h> #include <dm.h> +#include <log.h> +#include <net.h> #include <usb.h> #include <mmc.h> #include <nvme.h> @@ -20,6 +22,9 @@ #ifdef CONFIG_SANDBOX const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID; #endif +#ifdef CONFIG_VIRTIO_BLK +const efi_guid_t efi_guid_virtio_dev = U_BOOT_VIRTIO_DEV_GUID; +#endif /* template END node: */ static const struct efi_device_path END = { @@ -453,6 +458,11 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) return dp_size(dev->parent) + sizeof(struct efi_device_path_sd_mmc_path); #endif +#if defined(CONFIG_AHCI) || defined(CONFIG_SATA) + case UCLASS_AHCI: + return dp_size(dev->parent) + + sizeof(struct efi_device_path_sata); +#endif #if defined(CONFIG_NVME) case UCLASS_NVME: return dp_size(dev->parent) + @@ -468,6 +478,16 @@ __maybe_unused static unsigned int dp_size(struct udevice *dev) return dp_size(dev->parent) + sizeof(struct efi_device_path_vendor) + 1; #endif +#ifdef CONFIG_VIRTIO_BLK + case UCLASS_VIRTIO: + /* + * Virtio devices will be represented as a vendor + * device node with an extra byte for the device + * number. + */ + return dp_size(dev->parent) + + sizeof(struct efi_device_path_vendor) + 1; +#endif default: return dp_size(dev->parent); } @@ -530,7 +550,7 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) #ifdef CONFIG_SANDBOX case UCLASS_ROOT: { /* stop traversing parents at this point: */ - struct efi_device_path_vendor *dp = buf; + struct efi_device_path_vendor *dp; struct blk_desc *desc = dev_get_uclass_platdata(dev); dp_fill(buf, dev->parent); @@ -545,6 +565,23 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &dp->vendor_data[1]; } #endif +#ifdef CONFIG_VIRTIO_BLK + case UCLASS_VIRTIO: { + struct efi_device_path_vendor *dp; + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + dp_fill(buf, dev->parent); + dp = buf; + ++dp; + dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; + dp->dp.length = sizeof(*dp) + 1; + memcpy(&dp->guid, &efi_guid_virtio_dev, + sizeof(efi_guid_t)); + dp->vendor_data[0] = desc->devnum; + return &dp->vendor_data[1]; + } +#endif #ifdef CONFIG_IDE case UCLASS_IDE: { struct efi_device_path_atapi *dp = @@ -591,6 +628,22 @@ __maybe_unused static void *dp_fill(void *buf, struct udevice *dev) return &sddp[1]; } #endif +#if defined(CONFIG_AHCI) || defined(CONFIG_SATA) + case UCLASS_AHCI: { + struct efi_device_path_sata *dp = + dp_fill(buf, dev->parent); + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; + dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SATA; + dp->dp.length = sizeof(*dp); + dp->hba_port = desc->devnum; + /* default 0xffff implies no port multiplier */ + dp->port_multiplier_port = 0xffff; + dp->logical_unit_number = desc->lun; + return &dp[1]; + } +#endif #if defined(CONFIG_NVME) case UCLASS_NVME: { struct efi_device_path_nvme *dp = @@ -693,7 +746,7 @@ static unsigned dp_part_size(struct blk_desc *desc, int part) */ static void *dp_part_node(void *buf, struct blk_desc *desc, int part) { - disk_partition_t info; + struct disk_partition info; part_get_info(desc, part, &info); @@ -1035,7 +1088,7 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, { int is_net; struct blk_desc *desc = NULL; - disk_partition_t fs_partition; + struct disk_partition fs_partition; int part = 0; char filename[32] = { 0 }; /* dp->str is u16[32] long */ char *s; diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index af1adbb71ef..5ae4833fa78 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -6,6 +6,7 @@ */ #include <common.h> +#include <blk.h> #include <efi_loader.h> #define MAC_OUTPUT_LEN 22 @@ -148,6 +149,16 @@ static char *dp_msging(char *s, struct efi_device_path *dp) break; } + case DEVICE_PATH_SUB_TYPE_MSG_SATA: { + struct efi_device_path_sata *sdp = + (struct efi_device_path_sata *) dp; + + s += sprintf(s, "Sata(0x%x,0x%x,0x%x)", + sdp->hba_port, + sdp->port_multiplier_port, + sdp->logical_unit_number); + break; + } case DEVICE_PATH_SUB_TYPE_MSG_NVME: { struct efi_device_path_nvme *ndp = (struct efi_device_path_nvme *)dp; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index fd8fe175670..670bf2b8ef0 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -13,6 +13,8 @@ #include <part.h> #include <malloc.h> +struct efi_system_partition efi_system_partition; + const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID; /** @@ -354,6 +356,7 @@ static efi_status_t efi_disk_add_dev( struct efi_disk_obj **disk) { struct efi_disk_obj *diskobj; + struct efi_object *handle; efi_status_t ret; /* Don't add empty devices */ @@ -377,15 +380,25 @@ static efi_status_t efi_disk_add_dev( diskobj->dp = efi_dp_from_part(desc, part); } diskobj->part = part; - ret = efi_add_protocol(&diskobj->header, &efi_block_io_guid, - &diskobj->ops); - if (ret != EFI_SUCCESS) - return ret; - ret = efi_add_protocol(&diskobj->header, &efi_guid_device_path, - diskobj->dp); + + /* + * Install the device path and the block IO protocol. + * + * InstallMultipleProtocolInterfaces() checks if the device path is + * already installed on an other handle and returns EFI_ALREADY_STARTED + * in this case. + */ + handle = &diskobj->header; + ret = EFI_CALL(efi_install_multiple_protocol_interfaces( + &handle, &efi_guid_device_path, diskobj->dp, + &efi_block_io_guid, &diskobj->ops, NULL)); if (ret != EFI_SUCCESS) return ret; - /* partitions or whole disk without partitions */ + + /* + * On partitions or whole disks without partitions install the + * simple file system protocol if a file system is available. + */ if ((part || desc->part_type == PART_TYPE_UNKNOWN) && efi_fs_exists(desc, part)) { diskobj->volume = efi_simple_file_system(desc, part, @@ -418,6 +431,24 @@ static efi_status_t efi_disk_add_dev( diskobj->ops.media = &diskobj->media; if (disk) *disk = diskobj; + + /* Store first EFI system partition */ + if (part && !efi_system_partition.if_type) { + int r; + struct disk_partition info; + + r = part_get_info(desc, part, &info); + if (r) + return EFI_DEVICE_ERROR; + if (info.bootable & PART_EFI_SYSTEM_PARTITION) { + efi_system_partition.if_type = desc->if_type; + efi_system_partition.devnum = desc->devnum; + efi_system_partition.part = part; + EFI_PRINT("EFI system partition: %s %d:%d\n", + blk_get_if_type_name(desc->if_type), + desc->devnum, part); + } + } return EFI_SUCCESS; } @@ -439,7 +470,7 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, { int disks = 0; char devname[32] = { 0 }; /* dp->str is u16[32] long */ - disk_partition_t info; + struct disk_partition info; int part; struct efi_device_path *dp = NULL; efi_status_t ret; @@ -568,3 +599,32 @@ efi_status_t efi_disk_register(void) return EFI_SUCCESS; } + +/** + * efi_disk_is_system_part() - check if handle refers to an EFI system partition + * + * @handle: handle of partition + * + * Return: true if handle refers to an EFI system partition + */ +bool efi_disk_is_system_part(efi_handle_t handle) +{ + struct efi_handler *handler; + struct efi_disk_obj *diskobj; + struct disk_partition info; + efi_status_t ret; + int r; + + /* check if this is a block device */ + ret = efi_search_protocol(handle, &efi_block_io_guid, &handler); + if (ret != EFI_SUCCESS) + return false; + + diskobj = container_of(handle, struct efi_disk_obj, header); + + r = part_get_info(diskobj->desc, diskobj->part, &info); + if (r) + return false; + + return !!(info.bootable & PART_EFI_SYSTEM_PARTITION); +} diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 140116ddc4a..19afa69f530 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -8,9 +8,11 @@ #include <common.h> #include <charset.h> #include <efi_loader.h> +#include <log.h> #include <malloc.h> #include <mapmem.h> #include <fs.h> +#include <part.h> /* GUID for file system information */ const efi_guid_t efi_file_system_info_guid = EFI_FILE_SYSTEM_INFO_GUID; @@ -634,7 +636,7 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, utf8_utf16_strcpy(&dst, filename); } else if (!guidcmp(info_type, &efi_file_system_info_guid)) { struct efi_file_system_info *info = buffer; - disk_partition_t part; + struct disk_partition part; efi_uintn_t required_size; int r; diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index 1511e3bdb42..53f6d970f73 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -9,6 +9,7 @@ #include <dm.h> #include <efi_loader.h> #include <lcd.h> +#include <log.h> #include <malloc.h> #include <video.h> diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 6c270ce94f4..478aaf50d3a 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -13,7 +13,8 @@ #include <malloc.h> #include <pe.h> #include <sort.h> -#include "../lib/crypto/pkcs7_parser.h" +#include <crypto/pkcs7_parser.h> +#include <linux/err.h> const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; @@ -211,14 +212,16 @@ static void efi_set_code_and_data_type( #ifdef CONFIG_EFI_SECURE_BOOT /** - * cmp_pe_section - compare two sections - * @arg1: Pointer to pointer to first section - * @arg2: Pointer to pointer to second section + * cmp_pe_section() - compare virtual addresses of two PE image sections + * @arg1: pointer to pointer to first section header + * @arg2: pointer to pointer to second section header * - * Compare two sections in PE image. + * Compare the virtual addresses of two sections of an portable executable. + * The arguments are defined as const void * to allow usage with qsort(). * - * Return: -1, 0, 1 respectively if arg1 < arg2, arg1 == arg2 or - * arg1 > arg2 + * Return: -1 if the virtual address of arg1 is less than that of arg2, + * 0 if the virtual addresses are equal, 1 if the virtual address + * of arg1 is greater than that of arg2. */ static int cmp_pe_section(const void *arg1, const void *arg2) { @@ -236,7 +239,7 @@ static int cmp_pe_section(const void *arg1, const void *arg2) } /** - * efi_image_parse - parse a PE image + * efi_image_parse() - parse a PE image * @efi: Pointer to image * @len: Size of @efi * @regp: Pointer to a list of regions @@ -292,12 +295,12 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, efi_image_region_add(regs, efi, &opt->CheckSum, 0); if (nt64->OptionalHeader.NumberOfRvaAndSizes <= ctidx) { efi_image_region_add(regs, - &opt->CheckSum + 1, + &opt->Subsystem, efi + opt->SizeOfHeaders, 0); } else { /* Skip Certificates Table */ efi_image_region_add(regs, - &opt->CheckSum + 1, + &opt->Subsystem, &opt->DataDirectory[ctidx], 0); efi_image_region_add(regs, &opt->DataDirectory[ctidx] + 1, @@ -312,7 +315,7 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; efi_image_region_add(regs, efi, &opt->CheckSum, 0); - efi_image_region_add(regs, &opt->CheckSum + 1, + efi_image_region_add(regs, &opt->Subsystem, &opt->DataDirectory[ctidx], 0); efi_image_region_add(regs, &opt->DataDirectory[ctidx] + 1, efi + opt->SizeOfHeaders, 0); @@ -403,7 +406,7 @@ err: } /** - * efi_image_unsigned_authenticate - authenticate unsigned image with + * efi_image_unsigned_authenticate() - authenticate unsigned image with * SHA256 hash * @regs: List of regions to be verified * @@ -450,7 +453,7 @@ out: } /** - * efi_image_authenticate - verify a signature of signed image + * efi_image_authenticate() - verify a signature of signed image * @efi: Pointer to image * @efi_size: Size of @efi * @@ -538,8 +541,9 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) } msg = pkcs7_parse_message((void *)wincert + sizeof(*wincert), wincert->dwLength - sizeof(*wincert)); - if (!msg) { + if (IS_ERR(msg)) { debug("Parsing image's signature failed\n"); + msg = NULL; goto err; } @@ -633,21 +637,18 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, goto err; } - /* assume sizeof(IMAGE_NT_HEADERS32) <= sizeof(IMAGE_NT_HEADERS64) */ - if (efi_size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS32)) { + /* + * Check if the image section header fits into the file. Knowing that at + * least one section header follows we only need to check for the length + * of the 64bit header which is longer than the 32bit header. + */ + if (efi_size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS64)) { printf("%s: Invalid offset for Extended Header\n", __func__); ret = EFI_LOAD_ERROR; goto err; } nt = (void *) ((char *)efi + dos->e_lfanew); - if ((nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) && - (efi_size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS64))) { - printf("%s: Invalid offset for Extended Header\n", __func__); - ret = EFI_LOAD_ERROR; - goto err; - } - if (nt->Signature != IMAGE_NT_SIGNATURE) { printf("%s: Invalid NT Signature\n", __func__); ret = EFI_LOAD_ERROR; diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 97d90f069a6..44b8a2e09f0 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -11,6 +11,7 @@ #include <malloc.h> #include <mapmem.h> #include <watchdog.h> +#include <asm/cache.h> #include <linux/list_sort.h> #include <linux/sizes.h> @@ -229,7 +230,7 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map, } /** - * efi_add_memory_map() - add memory area to the memory map + * efi_add_memory_map_pg() - add pages to the memory map * * @start: start address, must be a multiple of EFI_PAGE_SIZE * @pages: number of pages to add @@ -237,8 +238,9 @@ static s64 efi_mem_carve_out(struct efi_mem_list *map, * @overlap_only_ram: the memory area must overlap existing * Return: status code */ -efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, - bool overlap_only_ram) +static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, + int memory_type, + bool overlap_only_ram) { struct list_head *lhandle; struct efi_mem_list *newlist; @@ -344,6 +346,28 @@ efi_status_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, } /** + * efi_add_memory_map() - add memory area to the memory map + * + * @start: start address of the memory area + * @size: length in bytes of the memory area + * @memory_type: type of memory added + * + * Return: status code + * + * This function automatically aligns the start and size of the memory area + * to EFI_PAGE_SIZE. + */ +efi_status_t efi_add_memory_map(u64 start, u64 size, int memory_type) +{ + u64 pages; + + pages = efi_size_in_pages(size + (start & EFI_PAGE_MASK)); + start &= ~EFI_PAGE_MASK; + + return efi_add_memory_map_pg(start, pages, memory_type, false); +} + +/** * efi_check_allocated() - validate address to be freed * * Check that the address is within allocated memory: @@ -469,7 +493,8 @@ efi_status_t efi_allocate_pages(int type, int memory_type, } /* Reserve that map in our memory maps */ - if (efi_add_memory_map(addr, pages, memory_type, true) != EFI_SUCCESS) + ret = efi_add_memory_map_pg(addr, pages, memory_type, true); + if (ret != EFI_SUCCESS) /* Map would overlap, bail out */ return EFI_OUT_OF_RESOURCES; @@ -514,7 +539,8 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) return EFI_INVALID_PARAMETER; } - ret = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false); + ret = efi_add_memory_map_pg(memory, pages, EFI_CONVENTIONAL_MEMORY, + false); /* Merging of adjacent free regions is missing */ if (ret != EFI_SUCCESS) @@ -680,8 +706,8 @@ efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end, pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT; - efi_add_memory_map(ram_start, pages, - EFI_CONVENTIONAL_MEMORY, false); + efi_add_memory_map_pg(ram_start, pages, + EFI_CONVENTIONAL_MEMORY, false); /* * Boards may indicate to the U-Boot memory core that they @@ -691,14 +717,14 @@ efi_status_t efi_add_conventional_memory_map(u64 ram_start, u64 ram_end, */ if (ram_top < ram_start) { /* ram_top is before this region, reserve all */ - efi_add_memory_map(ram_start, pages, - EFI_BOOT_SERVICES_DATA, true); + efi_add_memory_map_pg(ram_start, pages, + EFI_BOOT_SERVICES_DATA, true); } else if ((ram_top >= ram_start) && (ram_top < ram_end)) { /* ram_top is inside this region, reserve parts */ pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT; - efi_add_memory_map(ram_top, pages, - EFI_BOOT_SERVICES_DATA, true); + efi_add_memory_map_pg(ram_top, pages, + EFI_BOOT_SERVICES_DATA, true); } return EFI_SUCCESS; @@ -743,7 +769,8 @@ static void add_u_boot_and_runtime(void) uboot_stack_size) & ~EFI_PAGE_MASK; uboot_pages = ((uintptr_t)map_sysmem(gd->ram_top - 1, 0) - uboot_start + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; - efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false); + efi_add_memory_map_pg(uboot_start, uboot_pages, EFI_LOADER_DATA, + false); #if defined(__aarch64__) /* @@ -762,8 +789,8 @@ static void add_u_boot_and_runtime(void) runtime_end = (ulong)&__efi_runtime_stop; runtime_end = (runtime_end + runtime_mask) & ~runtime_mask; runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT; - efi_add_memory_map(runtime_start, runtime_pages, - EFI_RUNTIME_SERVICES_CODE, false); + efi_add_memory_map_pg(runtime_start, runtime_pages, + EFI_RUNTIME_SERVICES_CODE, false); } int efi_memory_init(void) diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 82d2595847a..22f0123eca4 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -18,6 +18,7 @@ #include <common.h> #include <efi_loader.h> #include <malloc.h> +#include <net.h> static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; static const efi_guid_t efi_pxe_base_code_protocol_guid = diff --git a/lib/efi_loader/efi_rng.c b/lib/efi_loader/efi_rng.c index a1d0ec842c8..caef4085b07 100644 --- a/lib/efi_loader/efi_rng.c +++ b/lib/efi_loader/efi_rng.c @@ -7,6 +7,7 @@ #include <dm.h> #include <efi_loader.h> #include <efi_rng.h> +#include <log.h> #include <rng.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 6a25acbbcdf..c0bd99b8674 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -11,6 +11,7 @@ #include <dm.h> #include <elf.h> #include <efi_loader.h> +#include <log.h> #include <malloc.h> #include <rtc.h> #include <u-boot/crc.h> @@ -784,11 +785,10 @@ out: efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len) { struct efi_runtime_mmio_list *newmmio; - u64 pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; uint64_t addr = *(uintptr_t *)mmio_ptr; efi_status_t ret; - ret = efi_add_memory_map(addr, pages, EFI_MMAP_IO, false); + ret = efi_add_memory_map(addr, len, EFI_MMAP_IO); if (ret != EFI_SUCCESS) return EFI_OUT_OF_RESOURCES; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 1b648c84673..dd0c53fc239 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -86,7 +86,7 @@ out: /** * efi_init_secure_boot - initialize secure boot state * - * Return: EFI_SUCCESS on success, status code (negative) on error + * Return: status code */ static efi_status_t efi_init_secure_boot(void) { @@ -135,6 +135,16 @@ efi_status_t efi_init_obj_list(void) /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */ switch_to_non_secure_mode(); + /* Initialize root node */ + ret = efi_root_node_register(); + if (ret != EFI_SUCCESS) + goto out; + +#ifdef CONFIG_PARTITIONS + ret = efi_disk_register(); + if (ret != EFI_SUCCESS) + goto out; +#endif /* Initialize variable services */ ret = efi_init_variables(); if (ret != EFI_SUCCESS) @@ -170,11 +180,6 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; - /* Initialize root node */ - ret = efi_root_node_register(); - if (ret != EFI_SUCCESS) - goto out; - /* Initialize EFI driver uclass */ ret = efi_driver_init(); if (ret != EFI_SUCCESS) @@ -183,11 +188,6 @@ efi_status_t efi_init_obj_list(void) ret = efi_console_register(); if (ret != EFI_SUCCESS) goto out; -#ifdef CONFIG_PARTITIONS - ret = efi_disk_register(); - if (ret != EFI_SUCCESS) - goto out; -#endif #if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) ret = efi_gop_register(); if (ret != EFI_SUCCESS) diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index 658e3547da3..6685253856a 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -10,11 +10,11 @@ #include <image.h> #include <hexdump.h> #include <malloc.h> +#include <crypto/pkcs7_parser.h> #include <linux/compat.h> #include <linux/oid_registry.h> #include <u-boot/rsa.h> #include <u-boot/sha256.h> -#include "../lib/crypto/pkcs7_parser.h" const efi_guid_t efi_guid_image_security_database = EFI_IMAGE_SECURITY_DATABASE_GUID; @@ -22,6 +22,7 @@ const efi_guid_t efi_guid_sha256 = EFI_CERT_SHA256_GUID; const efi_guid_t efi_guid_cert_rsa2048 = EFI_CERT_RSA2048_GUID; const efi_guid_t efi_guid_cert_x509 = EFI_CERT_X509_GUID; const efi_guid_t efi_guid_cert_x509_sha256 = EFI_CERT_X509_SHA256_GUID; +const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; #ifdef CONFIG_EFI_SECURE_BOOT @@ -528,7 +529,7 @@ out: * pointed to by @regs. If @nocheck is false, overlapping among entries * will be checked first. * - * Return: 0 on success, status code (negative) on error + * Return: status code */ efi_status_t efi_image_region_add(struct efi_image_regions *regs, const void *start, const void *end, @@ -667,7 +668,7 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl) esd = (struct efi_signature_data *) ((u8 *)esl + sizeof(*esl) + esl->signature_header_size); - while ((left > 0) && left >= esl->signature_size) { + while (left > 0) { /* Signature must exist if there is remaining data. */ if (left < esl->signature_size) { debug("Certificate is too small\n"); diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index a81488495e2..719d3e8880a 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -7,6 +7,7 @@ #include <common.h> #include <efi_loader.h> +#include <log.h> #include <mapmem.h> #include <smbios.h> diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 7df881a74b4..e097670e283 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -7,14 +7,17 @@ #include <common.h> #include <efi_loader.h> +#include <env.h> #include <env_internal.h> #include <hexdump.h> #include <malloc.h> #include <rtc.h> #include <search.h> +#include <uuid.h> +#include <crypto/pkcs7_parser.h> +#include <linux/bitops.h> #include <linux/compat.h> #include <u-boot/crc.h> -#include "../lib/crypto/pkcs7_parser.h" enum efi_secure_mode { EFI_MODE_SETUP, @@ -23,13 +26,24 @@ enum efi_secure_mode { EFI_MODE_DEPLOYED, }; -const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; static bool efi_secure_boot; static int efi_secure_mode; static u8 efi_vendor_keys; #define READ_ONLY BIT(31) +static efi_status_t efi_get_variable_common(u16 *variable_name, + const efi_guid_t *vendor, + u32 *attributes, + efi_uintn_t *data_size, void *data); + +static efi_status_t efi_set_variable_common(u16 *variable_name, + const efi_guid_t *vendor, + u32 attributes, + efi_uintn_t data_size, + const void *data, + bool ro_check); + /* * Mapping between EFI variables and u-boot variables: * @@ -169,176 +183,95 @@ static const char *parse_attr(const char *str, u32 *attrp, u64 *timep) return str; } -static efi_status_t efi_set_variable_internal(u16 *variable_name, - const efi_guid_t *vendor, - u32 attributes, - efi_uintn_t data_size, - const void *data, - bool ro_check); +/** + * efi_set_secure_state - modify secure boot state variables + * @sec_boot: value of SecureBoot + * @setup_mode: value of SetupMode + * @audit_mode: value of AuditMode + * @deployed_mode: value of DeployedMode + * + * Modify secure boot stat-related variables as indicated. + * + * Return: status code + */ +static efi_status_t efi_set_secure_state(int sec_boot, int setup_mode, + int audit_mode, int deployed_mode) +{ + u32 attributes; + efi_status_t ret; + + attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | + READ_ONLY; + ret = efi_set_variable_common(L"SecureBoot", &efi_global_variable_guid, + attributes, sizeof(sec_boot), &sec_boot, + false); + if (ret != EFI_SUCCESS) + goto err; + + ret = efi_set_variable_common(L"SetupMode", &efi_global_variable_guid, + attributes, sizeof(setup_mode), + &setup_mode, false); + if (ret != EFI_SUCCESS) + goto err; + + ret = efi_set_variable_common(L"AuditMode", &efi_global_variable_guid, + attributes, sizeof(audit_mode), + &audit_mode, false); + if (ret != EFI_SUCCESS) + goto err; + + ret = efi_set_variable_common(L"DeployedMode", + &efi_global_variable_guid, attributes, + sizeof(deployed_mode), &deployed_mode, + false); +err: + return ret; +} /** * efi_transfer_secure_state - handle a secure boot state transition * @mode: new state * * Depending on @mode, secure boot related variables are updated. - * Those variables are *read-only* for users, efi_set_variable_internal() + * Those variables are *read-only* for users, efi_set_variable_common() * is called here. * - * Return: EFI_SUCCESS on success, status code (negative) on error + * Return: status code */ static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode) { - u32 attributes; - u8 val; efi_status_t ret; - debug("Secure state from %d to %d\n", efi_secure_mode, mode); + debug("Switching secure state from %d to %d\n", efi_secure_mode, mode); - attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS; if (mode == EFI_MODE_DEPLOYED) { - val = 1; - ret = efi_set_variable_internal(L"SecureBoot", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"SetupMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"AuditMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 1; - ret = efi_set_variable_internal(L"DeployedMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); + ret = efi_set_secure_state(1, 0, 0, 1); if (ret != EFI_SUCCESS) goto err; efi_secure_boot = true; } else if (mode == EFI_MODE_AUDIT) { - ret = efi_set_variable_internal(L"PK", - &efi_global_variable_guid, - attributes, - 0, NULL, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"SecureBoot", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 1; - ret = efi_set_variable_internal(L"SetupMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); + ret = efi_set_variable_common(L"PK", &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + 0, NULL, false); if (ret != EFI_SUCCESS) goto err; - val = 1; - ret = efi_set_variable_internal(L"AuditMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"DeployedMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); + + ret = efi_set_secure_state(0, 1, 1, 0); if (ret != EFI_SUCCESS) goto err; efi_secure_boot = true; } else if (mode == EFI_MODE_USER) { - val = 1; - ret = efi_set_variable_internal(L"SecureBoot", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"SetupMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"AuditMode", - &efi_global_variable_guid, - attributes, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"DeployedMode", - &efi_global_variable_guid, - attributes, - sizeof(val), &val, - false); + ret = efi_set_secure_state(1, 0, 0, 0); if (ret != EFI_SUCCESS) goto err; efi_secure_boot = true; } else if (mode == EFI_MODE_SETUP) { - val = 0; - ret = efi_set_variable_internal(L"SecureBoot", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 1; - ret = efi_set_variable_internal(L"SetupMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"AuditMode", - &efi_global_variable_guid, - attributes, - sizeof(val), &val, - false); - if (ret != EFI_SUCCESS) - goto err; - val = 0; - ret = efi_set_variable_internal(L"DeployedMode", - &efi_global_variable_guid, - attributes | READ_ONLY, - sizeof(val), &val, - false); + ret = efi_set_secure_state(0, 1, 0, 0); if (ret != EFI_SUCCESS) goto err; } else { @@ -358,7 +291,7 @@ err: /** * efi_init_secure_state - initialize secure boot state * - * Return: EFI_SUCCESS on success, status code (negative) on error + * Return: status code */ static efi_status_t efi_init_secure_state(void) { @@ -374,8 +307,8 @@ static efi_status_t efi_init_secure_state(void) */ size = 0; - ret = EFI_CALL(efi_get_variable(L"PK", &efi_global_variable_guid, - NULL, &size, NULL)); + ret = efi_get_variable_common(L"PK", &efi_global_variable_guid, + NULL, &size, NULL); if (ret == EFI_BUFFER_TOO_SMALL) { if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) mode = EFI_MODE_USER; @@ -392,14 +325,13 @@ static efi_status_t efi_init_secure_state(void) ret = efi_transfer_secure_state(mode); if (ret == EFI_SUCCESS) - ret = efi_set_variable_internal(L"VendorKeys", - &efi_global_variable_guid, - EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_RUNTIME_ACCESS - | READ_ONLY, - sizeof(efi_vendor_keys), - &efi_vendor_keys, - false); + ret = efi_set_variable_common(L"VendorKeys", + &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | + READ_ONLY, + sizeof(efi_vendor_keys), + &efi_vendor_keys, false); err: return ret; @@ -513,7 +445,7 @@ out: * attributes and signed time will also be returned in @env_attr and @time, * respectively. * - * Return: EFI_SUCCESS on success, status code (negative) on error + * Return: status code */ static efi_status_t efi_variable_authenticate(u16 *variable, const efi_guid_t *vendor, @@ -594,9 +526,8 @@ static efi_status_t efi_variable_authenticate(u16 *variable, var_sig = efi_variable_parse_signature(auth->auth_info.cert_data, auth->auth_info.hdr.dwLength - sizeof(auth->auth_info)); - if (IS_ERR(var_sig)) { + if (!var_sig) { debug("Parsing variable's signature failed\n"); - var_sig = NULL; goto err; } @@ -662,12 +593,10 @@ static efi_status_t efi_variable_authenticate(u16 *variable, } #endif /* CONFIG_EFI_SECURE_BOOT */ -static -efi_status_t EFIAPI efi_get_variable_common(u16 *variable_name, +static efi_status_t efi_get_variable_common(u16 *variable_name, const efi_guid_t *vendor, u32 *attributes, - efi_uintn_t *data_size, void *data, - bool is_non_volatile) + efi_uintn_t *data_size, void *data) { char *native_name; efi_status_t ret; @@ -750,27 +679,6 @@ out: return ret; } -static -efi_status_t EFIAPI efi_get_volatile_variable(u16 *variable_name, - const efi_guid_t *vendor, - u32 *attributes, - efi_uintn_t *data_size, - void *data) -{ - return efi_get_variable_common(variable_name, vendor, attributes, - data_size, data, false); -} - -efi_status_t EFIAPI efi_get_nonvolatile_variable(u16 *variable_name, - const efi_guid_t *vendor, - u32 *attributes, - efi_uintn_t *data_size, - void *data) -{ - return efi_get_variable_common(variable_name, vendor, attributes, - data_size, data, true); -} - /** * efi_efi_get_variable() - retrieve value of a UEFI variable * @@ -795,12 +703,8 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes, data_size, data); - ret = efi_get_volatile_variable(variable_name, vendor, attributes, - data_size, data); - if (ret == EFI_NOT_FOUND) - ret = efi_get_nonvolatile_variable(variable_name, vendor, - attributes, data_size, data); - + ret = efi_get_variable_common(variable_name, vendor, attributes, + data_size, data); return EFI_EXIT(ret); } @@ -865,7 +769,10 @@ static efi_status_t parse_uboot_variable(char *variable, /* guid */ c = *(name - 1); *(name - 1) = '\0'; /* guid need be null-terminated here */ - uuid_str_to_bin(guid, (unsigned char *)vendor, UUID_STR_FORMAT_GUID); + if (uuid_str_to_bin(guid, (unsigned char *)vendor, + UUID_STR_FORMAT_GUID)) + /* The only error would be EINVAL. */ + return EFI_INVALID_PARAMETER; *(name - 1) = c; /* attributes */ @@ -964,14 +871,12 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, return EFI_EXIT(ret); } -static -efi_status_t EFIAPI efi_set_variable_common(u16 *variable_name, +static efi_status_t efi_set_variable_common(u16 *variable_name, const efi_guid_t *vendor, u32 attributes, efi_uintn_t data_size, const void *data, - bool ro_check, - bool is_non_volatile) + bool ro_check) { char *native_name = NULL, *old_data = NULL, *val = NULL, *s; efi_uintn_t old_size; @@ -980,8 +885,6 @@ efi_status_t EFIAPI efi_set_variable_common(u16 *variable_name, u32 attr; efi_status_t ret = EFI_SUCCESS; - debug("%s: set '%s'\n", __func__, native_name); - if (!variable_name || !*variable_name || !vendor || ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) && !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) { @@ -996,16 +899,8 @@ efi_status_t EFIAPI efi_set_variable_common(u16 *variable_name, /* check if a variable exists */ old_size = 0; attr = 0; - ret = EFI_CALL(efi_get_variable(variable_name, vendor, &attr, - &old_size, NULL)); - if (ret == EFI_BUFFER_TOO_SMALL) { - if ((is_non_volatile && !(attr & EFI_VARIABLE_NON_VOLATILE)) || - (!is_non_volatile && (attr & EFI_VARIABLE_NON_VOLATILE))) { - ret = EFI_INVALID_PARAMETER; - goto err; - } - } - + ret = efi_get_variable_common(variable_name, vendor, &attr, + &old_size, NULL); append = !!(attributes & EFI_VARIABLE_APPEND_WRITE); attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE; delete = !append && (!data_size || !attributes); @@ -1092,11 +987,11 @@ efi_status_t EFIAPI efi_set_variable_common(u16 *variable_name, if (append) { old_data = malloc(old_size); if (!old_data) { - return EFI_OUT_OF_RESOURCES; + ret = EFI_OUT_OF_RESOURCES; goto err; } - ret = EFI_CALL(efi_get_variable(variable_name, vendor, - &attr, &old_size, old_data)); + ret = efi_get_variable_common(variable_name, vendor, + &attr, &old_size, old_data); if (ret != EFI_SUCCESS) goto err; } else { @@ -1179,7 +1074,7 @@ out: /* update VendorKeys */ if (vendor_keys_modified & efi_vendor_keys) { efi_vendor_keys = 0; - ret = efi_set_variable_internal( + ret = efi_set_variable_common( L"VendorKeys", &efi_global_variable_guid, EFI_VARIABLE_BOOTSERVICE_ACCESS @@ -1201,54 +1096,6 @@ err: return ret; } -static -efi_status_t EFIAPI efi_set_volatile_variable(u16 *variable_name, - const efi_guid_t *vendor, - u32 attributes, - efi_uintn_t data_size, - const void *data, - bool ro_check) -{ - return efi_set_variable_common(variable_name, vendor, attributes, - data_size, data, ro_check, false); -} - -efi_status_t EFIAPI efi_set_nonvolatile_variable(u16 *variable_name, - const efi_guid_t *vendor, - u32 attributes, - efi_uintn_t data_size, - const void *data, - bool ro_check) -{ - efi_status_t ret; - - ret = efi_set_variable_common(variable_name, vendor, attributes, - data_size, data, ro_check, true); - - return ret; -} - -static efi_status_t efi_set_variable_internal(u16 *variable_name, - const efi_guid_t *vendor, - u32 attributes, - efi_uintn_t data_size, - const void *data, - bool ro_check) -{ - efi_status_t ret; - - if (attributes & EFI_VARIABLE_NON_VOLATILE) - ret = efi_set_nonvolatile_variable(variable_name, vendor, - attributes, - data_size, data, ro_check); - else - ret = efi_set_volatile_variable(variable_name, vendor, - attributes, data_size, data, - ro_check); - - return ret; -} - /** * efi_set_variable() - set value of a UEFI variable * @@ -1274,9 +1121,9 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, /* READ_ONLY bit is not part of API */ attributes &= ~(u32)READ_ONLY; - return EFI_EXIT(efi_set_variable_internal(variable_name, vendor, - attributes, data_size, data, - true)); + return EFI_EXIT(efi_set_variable_common(variable_name, vendor, + attributes, data_size, data, + true)); } /** diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c new file mode 100644 index 00000000000..cacc76e23db --- /dev/null +++ b/lib/efi_loader/efi_variable_tee.c @@ -0,0 +1,662 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI variable service via OP-TEE + * + * Copyright (C) 2019 Linaro Ltd. <sughosh.ganu@linaro.org> + * Copyright (C) 2019 Linaro Ltd. <ilias.apalodimas@linaro.org> + */ + +#include <common.h> +#include <efi.h> +#include <efi_api.h> +#include <efi_loader.h> +#include <tee.h> +#include <malloc.h> +#include <mm_communication.h> + +static efi_uintn_t max_buffer_size; /* comm + var + func + data */ +static efi_uintn_t max_payload_size; /* func + data */ + +struct mm_connection { + struct udevice *tee; + u32 session; +}; + +/** + * get_connection() - Retrieve OP-TEE session for a specific UUID. + * + * @conn: session buffer to fill + * Return: status code + */ +static int get_connection(struct mm_connection *conn) +{ + static const struct tee_optee_ta_uuid uuid = PTA_STMM_UUID; + struct udevice *tee = NULL; + struct tee_open_session_arg arg; + int rc; + + tee = tee_find_device(tee, NULL, NULL, NULL); + if (!tee) + return -ENODEV; + + memset(&arg, 0, sizeof(arg)); + tee_optee_ta_uuid_to_octets(arg.uuid, &uuid); + rc = tee_open_session(tee, &arg, 0, NULL); + if (!rc) { + conn->tee = tee; + conn->session = arg.session; + } + + return rc; +} + +/** + * optee_mm_communicate() - Pass a buffer to StandaloneMM running in OP-TEE + * + * @comm_buf: locally allocted communcation buffer + * @dsize: buffer size + * Return: status code + */ +static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize) +{ + ulong buf_size; + efi_status_t ret; + struct efi_mm_communicate_header *mm_hdr; + struct mm_connection conn = { NULL, 0 }; + struct tee_invoke_arg arg; + struct tee_param param[2]; + struct tee_shm *shm = NULL; + int rc; + + if (!comm_buf) + return EFI_INVALID_PARAMETER; + + mm_hdr = (struct efi_mm_communicate_header *)comm_buf; + buf_size = mm_hdr->message_len + sizeof(efi_guid_t) + sizeof(size_t); + + if (dsize != buf_size) + return EFI_INVALID_PARAMETER; + + rc = get_connection(&conn); + if (rc) { + log_err("Unable to open OP-TEE session (err=%d)\n", rc); + return EFI_UNSUPPORTED; + } + + if (tee_shm_register(conn.tee, comm_buf, buf_size, 0, &shm)) { + log_err("Unable to register shared memory\n"); + return EFI_UNSUPPORTED; + } + + memset(&arg, 0, sizeof(arg)); + arg.func = PTA_STMM_CMDID_COMMUNICATE; + arg.session = conn.session; + + memset(param, 0, sizeof(param)); + param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; + param[0].u.memref.size = buf_size; + param[0].u.memref.shm = shm; + param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; + + rc = tee_invoke_func(conn.tee, &arg, 2, param); + if (rc) + return EFI_INVALID_PARAMETER; + tee_shm_free(shm); + tee_close_session(conn.tee, conn.session); + + switch (param[1].u.value.a) { + case ARM_SMC_MM_RET_SUCCESS: + ret = EFI_SUCCESS; + break; + + case ARM_SMC_MM_RET_INVALID_PARAMS: + ret = EFI_INVALID_PARAMETER; + break; + + case ARM_SMC_MM_RET_DENIED: + ret = EFI_ACCESS_DENIED; + break; + + case ARM_SMC_MM_RET_NO_MEMORY: + ret = EFI_OUT_OF_RESOURCES; + break; + + default: + ret = EFI_ACCESS_DENIED; + } + + return ret; +} + +/** + * mm_communicate() - Adjust the cmonnucation buffer to StandAlonneMM and send + * it to OP-TEE + * + * @comm_buf: locally allocted communcation buffer + * @dsize: buffer size + * Return: status code + */ +static efi_status_t mm_communicate(u8 *comm_buf, efi_uintn_t dsize) +{ + efi_status_t ret; + struct efi_mm_communicate_header *mm_hdr; + struct smm_variable_communicate_header *var_hdr; + + dsize += MM_COMMUNICATE_HEADER_SIZE + MM_VARIABLE_COMMUNICATE_SIZE; + mm_hdr = (struct efi_mm_communicate_header *)comm_buf; + var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data; + + ret = optee_mm_communicate(comm_buf, dsize); + if (ret != EFI_SUCCESS) { + log_err("%s failed!\n", __func__); + return ret; + } + + return var_hdr->ret_status; +} + +/** + * setup_mm_hdr() - Allocate a buffer for StandAloneMM and initialize the + * header data. + * + * @dptr: pointer address of the corresponding StandAloneMM + * function + * @payload_size: buffer size + * @func: standAloneMM function number + * @ret: EFI return code + * Return: buffer or NULL + */ +static u8 *setup_mm_hdr(void **dptr, efi_uintn_t payload_size, + efi_uintn_t func, efi_status_t *ret) +{ + const efi_guid_t mm_var_guid = EFI_MM_VARIABLE_GUID; + struct efi_mm_communicate_header *mm_hdr; + struct smm_variable_communicate_header *var_hdr; + u8 *comm_buf; + + /* In the init function we initialize max_buffer_size with + * get_max_payload(). So skip the test if max_buffer_size is initialized + * StandAloneMM will perform similar checks and drop the buffer if it's + * too long + */ + if (max_buffer_size && max_buffer_size < + (MM_COMMUNICATE_HEADER_SIZE + + MM_VARIABLE_COMMUNICATE_SIZE + + payload_size)) { + *ret = EFI_INVALID_PARAMETER; + return NULL; + } + + comm_buf = calloc(1, MM_COMMUNICATE_HEADER_SIZE + + MM_VARIABLE_COMMUNICATE_SIZE + + payload_size); + if (!comm_buf) { + *ret = EFI_OUT_OF_RESOURCES; + return NULL; + } + + mm_hdr = (struct efi_mm_communicate_header *)comm_buf; + guidcpy(&mm_hdr->header_guid, &mm_var_guid); + mm_hdr->message_len = MM_VARIABLE_COMMUNICATE_SIZE + payload_size; + + var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data; + var_hdr->function = func; + if (dptr) + *dptr = var_hdr->data; + *ret = EFI_SUCCESS; + + return comm_buf; +} + +/** + * get_max_payload() - Get variable payload size from StandAloneMM. + * + * @size: size of the variable in storage + * Return: status code + */ +efi_status_t EFIAPI get_max_payload(efi_uintn_t *size) +{ + struct smm_variable_payload_size *var_payload = NULL; + efi_uintn_t payload_size; + u8 *comm_buf = NULL; + efi_status_t ret; + + if (!size) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + payload_size = sizeof(*var_payload); + comm_buf = setup_mm_hdr((void **)&var_payload, payload_size, + SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE, &ret); + if (!comm_buf) + goto out; + + ret = mm_communicate(comm_buf, payload_size); + if (ret != EFI_SUCCESS) + goto out; + + *size = var_payload->size; + +out: + free(comm_buf); + return ret; +} + +/** + * efi_get_variable() - retrieve value of a UEFI variable + * + * This function implements the GetVariable runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @name: name of the variable + * @guid: vendor GUID + * @attr: attributes of the variable + * @data_size: size of the buffer to which the variable value is copied + * @data: buffer to which the variable value is copied + * Return: status code + */ +efi_status_t EFIAPI efi_get_variable(u16 *name, const efi_guid_t *guid, + u32 *attr, efi_uintn_t *data_size, + void *data) +{ + struct smm_variable_access *var_acc; + efi_uintn_t payload_size; + efi_uintn_t name_size; + efi_uintn_t tmp_dsize; + u8 *comm_buf = NULL; + efi_status_t ret; + + EFI_ENTRY("\"%ls\" %pUl %p %p %p", name, guid, attr, data_size, data); + + if (!name || !guid || !data_size) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* Check payload size */ + name_size = u16_strsize(name); + if (name_size > max_payload_size - MM_VARIABLE_ACCESS_HEADER_SIZE) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* Trim output buffer size */ + tmp_dsize = *data_size; + if (name_size + tmp_dsize > + max_payload_size - MM_VARIABLE_ACCESS_HEADER_SIZE) { + tmp_dsize = max_payload_size - + MM_VARIABLE_ACCESS_HEADER_SIZE - + name_size; + } + + /* Get communication buffer and initialize header */ + payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + tmp_dsize; + comm_buf = setup_mm_hdr((void **)&var_acc, payload_size, + SMM_VARIABLE_FUNCTION_GET_VARIABLE, &ret); + if (!comm_buf) + goto out; + + /* Fill in contents */ + guidcpy(&var_acc->guid, guid); + var_acc->data_size = tmp_dsize; + var_acc->name_size = name_size; + var_acc->attr = attr ? *attr : 0; + memcpy(var_acc->name, name, name_size); + + /* Communicate */ + ret = mm_communicate(comm_buf, payload_size); + if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) { + /* Update with reported data size for trimmed case */ + *data_size = var_acc->data_size; + } + if (ret != EFI_SUCCESS) + goto out; + + if (attr) + *attr = var_acc->attr; + if (data) + memcpy(data, (u8 *)var_acc->name + var_acc->name_size, + var_acc->data_size); + else + ret = EFI_INVALID_PARAMETER; + +out: + free(comm_buf); + return EFI_EXIT(ret); +} + +/** + * efi_get_next_variable_name() - enumerate the current variable names + * + * @variable_name_size: size of variable_name buffer in bytes + * @variable_name: name of uefi variable's name in u16 + * @guid: vendor's guid + * + * This function implements the GetNextVariableName service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * Return: status code + */ +efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, + u16 *variable_name, + efi_guid_t *guid) +{ + struct smm_variable_getnext *var_getnext; + efi_uintn_t payload_size; + efi_uintn_t out_name_size; + efi_uintn_t in_name_size; + efi_uintn_t tmp_dsize; + efi_uintn_t name_size; + u8 *comm_buf = NULL; + efi_status_t ret; + + EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, guid); + + if (!variable_name_size || !variable_name || !guid) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + out_name_size = *variable_name_size; + in_name_size = u16_strsize(variable_name); + + if (out_name_size < in_name_size) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + name_size = u16_strsize(variable_name); + if (name_size > max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* Trim output buffer size */ + tmp_dsize = *variable_name_size; + if (name_size + tmp_dsize > + max_payload_size - MM_VARIABLE_GET_NEXT_HEADER_SIZE) { + tmp_dsize = max_payload_size - + MM_VARIABLE_GET_NEXT_HEADER_SIZE - + name_size; + } + + payload_size = MM_VARIABLE_GET_NEXT_HEADER_SIZE + out_name_size; + comm_buf = setup_mm_hdr((void **)&var_getnext, payload_size, + SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME, + &ret); + if (!comm_buf) + goto out; + + /* Fill in contents */ + guidcpy(&var_getnext->guid, guid); + var_getnext->name_size = out_name_size; + memcpy(var_getnext->name, variable_name, in_name_size); + memset((u8 *)var_getnext->name + in_name_size, 0x0, + out_name_size - in_name_size); + + /* Communicate */ + ret = mm_communicate(comm_buf, payload_size); + if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) { + /* Update with reported data size for trimmed case */ + *variable_name_size = var_getnext->name_size; + } + if (ret != EFI_SUCCESS) + goto out; + + guidcpy(guid, &var_getnext->guid); + memcpy(variable_name, (u8 *)var_getnext->name, + var_getnext->name_size); + +out: + free(comm_buf); + return EFI_EXIT(ret); +} + +/** + * efi_set_variable() - set value of a UEFI variable + * + * This function implements the SetVariable runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @name: name of the variable + * @guid: vendor GUID + * @attr: attributes of the variable + * @data_size: size of the buffer with the variable value + * @data: buffer with the variable value + * Return: status code + */ +efi_status_t EFIAPI efi_set_variable(u16 *name, const efi_guid_t *guid, + u32 attr, efi_uintn_t data_size, + const void *data) +{ + struct smm_variable_access *var_acc; + efi_uintn_t payload_size; + efi_uintn_t name_size; + u8 *comm_buf = NULL; + efi_status_t ret; + + EFI_ENTRY("\"%ls\" %pUl %x %zu %p", name, guid, attr, data_size, data); + + if (!name || name[0] == 0 || !guid) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + if (data_size > 0 && !data) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* Check payload size */ + name_size = u16_strsize(name); + payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + data_size; + if (payload_size > max_payload_size) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* Get communication buffer and initialize header */ + comm_buf = setup_mm_hdr((void **)&var_acc, payload_size, + SMM_VARIABLE_FUNCTION_SET_VARIABLE, &ret); + if (!comm_buf) + goto out; + + /* Fill in contents */ + guidcpy(&var_acc->guid, guid); + var_acc->data_size = data_size; + var_acc->name_size = name_size; + var_acc->attr = attr; + memcpy(var_acc->name, name, name_size); + memcpy((u8 *)var_acc->name + name_size, data, data_size); + + /* Communicate */ + ret = mm_communicate(comm_buf, payload_size); + +out: + free(comm_buf); + return EFI_EXIT(ret); +} + +/** + * efi_query_variable_info() - get information about EFI variables + * + * This function implements the QueryVariableInfo() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @attributes: bitmask to select variables to be + * queried + * @maximum_variable_storage_size: maximum size of storage area for the + * selected variable types + * @remaining_variable_storage_size: remaining size of storage are for the + * selected variable types + * @maximum_variable_size: maximum size of a variable of the + * selected type + * Returns: status code + */ +efi_status_t EFIAPI __efi_runtime +efi_query_variable_info(u32 attributes, u64 *max_variable_storage_size, + u64 *remain_variable_storage_size, + u64 *max_variable_size) +{ + struct smm_variable_query_info *mm_query_info; + efi_uintn_t payload_size; + efi_status_t ret; + u8 *comm_buf; + + EFI_ENTRY("%x %p %p %p", attributes, max_variable_storage_size, + remain_variable_storage_size, max_variable_size); + + payload_size = sizeof(*mm_query_info); + comm_buf = setup_mm_hdr((void **)&mm_query_info, payload_size, + SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO, + &ret); + if (!comm_buf) + goto out; + + mm_query_info->attr = attributes; + ret = mm_communicate(comm_buf, payload_size); + if (ret != EFI_SUCCESS) + goto out; + *max_variable_storage_size = mm_query_info->max_variable_storage; + *remain_variable_storage_size = + mm_query_info->remaining_variable_storage; + *max_variable_size = mm_query_info->max_variable_size; + +out: + free(comm_buf); + return EFI_EXIT(ret); +} + +/** + * efi_get_variable_runtime() - runtime implementation of GetVariable() + * + * @variable_name: name of the variable + * @guid: vendor GUID + * @attributes: attributes of the variable + * @data_size: size of the buffer to which the variable value is copied + * @data: buffer to which the variable value is copied + * Return: status code + */ +static efi_status_t __efi_runtime EFIAPI +efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *guid, + u32 *attributes, efi_uintn_t *data_size, void *data) +{ + return EFI_UNSUPPORTED; +} + +/** + * efi_get_next_variable_name_runtime() - runtime implementation of + * GetNextVariable() + * + * @variable_name_size: size of variable_name buffer in byte + * @variable_name: name of uefi variable's name in u16 + * @guid: vendor's guid + * Return: status code + */ +static efi_status_t __efi_runtime EFIAPI +efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size, + u16 *variable_name, efi_guid_t *guid) +{ + return EFI_UNSUPPORTED; +} + +/** + * efi_query_variable_info() - get information about EFI variables + * + * This function implements the QueryVariableInfo() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @attributes: bitmask to select variables to be + * queried + * @maximum_variable_storage_size: maximum size of storage area for the + * selected variable types + * @remaining_variable_storage_size: remaining size of storage are for the + * selected variable types + * @maximum_variable_size: maximum size of a variable of the + * selected type + * Return: status code + */ +efi_status_t EFIAPI __efi_runtime +efi_query_variable_info_runtime(u32 attributes, u64 *max_variable_storage_size, + u64 *remain_variable_storage_size, + u64 *max_variable_size) +{ + return EFI_UNSUPPORTED; +} + +/** + * efi_set_variable_runtime() - runtime implementation of SetVariable() + * + * @variable_name: name of the variable + * @guid: vendor GUID + * @attributes: attributes of the variable + * @data_size: size of the buffer with the variable value + * @data: buffer with the variable value + * Return: status code + */ +static efi_status_t __efi_runtime EFIAPI +efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *guid, + u32 attributes, efi_uintn_t data_size, + const void *data) +{ + return EFI_UNSUPPORTED; +} + +/** + * efi_variables_boot_exit_notify() - notify ExitBootServices() is called + */ +void efi_variables_boot_exit_notify(void) +{ + u8 *comm_buf; + efi_status_t ret; + + comm_buf = setup_mm_hdr(NULL, 0, + SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE, &ret); + if (comm_buf) + ret = mm_communicate(comm_buf, 0); + else + ret = EFI_NOT_FOUND; + + if (ret != EFI_SUCCESS) + log_err("Unable to notify StMM for ExitBootServices\n"); + free(comm_buf); + + /* Update runtime service table */ + efi_runtime_services.query_variable_info = + efi_query_variable_info_runtime; + efi_runtime_services.get_variable = efi_get_variable_runtime; + efi_runtime_services.get_next_variable_name = + efi_get_next_variable_name_runtime; + efi_runtime_services.set_variable = efi_set_variable_runtime; + efi_update_table_header_crc32(&efi_runtime_services.hdr); +} + +/** + * efi_init_variables() - initialize variable services + * + * Return: status code + */ +efi_status_t efi_init_variables(void) +{ + efi_status_t ret; + + ret = get_max_payload(&max_payload_size); + if (ret != EFI_SUCCESS) + return ret; + + max_buffer_size = MM_COMMUNICATE_HEADER_SIZE + + MM_VARIABLE_COMMUNICATE_SIZE + + max_payload_size; + + return EFI_SUCCESS; +} diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index d98a854e6d1..5eb297d285a 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -15,6 +15,7 @@ #include <efi_selftest.h> #include "efi_selftest_disk_image.h" +#include <asm/cache.h> /* Block size of compressed disk image */ #define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8 diff --git a/lib/efi_selftest/efi_selftest_console.c b/lib/efi_selftest/efi_selftest_console.c index 42f51b65203..13f3ee6bc19 100644 --- a/lib/efi_selftest/efi_selftest_console.c +++ b/lib/efi_selftest/efi_selftest_console.c @@ -6,6 +6,7 @@ */ #include <efi_selftest.h> +#include <net.h> #include <vsprintf.h> struct efi_simple_text_output_protocol *con_out; diff --git a/lib/efi_selftest/efi_selftest_memory.c b/lib/efi_selftest/efi_selftest_memory.c index e71732dc6db..4d32a280061 100644 --- a/lib/efi_selftest/efi_selftest_memory.c +++ b/lib/efi_selftest/efi_selftest_memory.c @@ -176,9 +176,9 @@ static int execute(void) /* Check memory reservation for the device tree */ if (fdt_addr && find_in_memory_map(map_size, memory_map, desc_size, fdt_addr, - EFI_BOOT_SERVICES_DATA) != EFI_ST_SUCCESS) { + EFI_ACPI_RECLAIM_MEMORY) != EFI_ST_SUCCESS) { efi_st_error - ("Device tree not marked as boot services data\n"); + ("Device tree not marked as ACPI reclaim memory\n"); return EFI_ST_FAILURE; } return EFI_ST_SUCCESS; diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index 9797ecaf42e..79f04678039 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -15,6 +15,7 @@ */ #include <efi_selftest.h> +#include <net.h> /* * MAC address for broadcasts diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 0a3b8607822..1f2b763acc3 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -9,7 +9,9 @@ #include <dm.h> #include <hang.h> #include <init.h> +#include <log.h> #include <malloc.h> +#include <net.h> #include <dm/of_extra.h> #include <env.h> #include <errno.h> @@ -1472,8 +1474,14 @@ int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name, return 0; } +__weak int fdtdec_board_setup(const void *fdt_blob) +{ + return 0; +} + int fdtdec_setup(void) { + int ret; #if CONFIG_IS_ENABLED(OF_CONTROL) # if CONFIG_IS_ENABLED(MULTI_DTB_FIT) void *fdt_blob; @@ -1526,7 +1534,10 @@ int fdtdec_setup(void) # endif #endif - return fdtdec_prepare_fdt(); + ret = fdtdec_prepare_fdt(); + if (!ret) + ret = fdtdec_board_setup(gd->fdt_blob); + return ret; } #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) diff --git a/lib/fdtdec_common.c b/lib/fdtdec_common.c index 5775992ef33..ddaca0087e1 100644 --- a/lib/fdtdec_common.c +++ b/lib/fdtdec_common.c @@ -9,6 +9,7 @@ #ifndef USE_HOSTCC #include <common.h> +#include <log.h> #include <linux/libfdt.h> #include <fdtdec.h> #else diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c index e8bfd1fb1ec..e0c6e0971cd 100644 --- a/lib/fdtdec_test.c +++ b/lib/fdtdec_test.c @@ -7,6 +7,7 @@ */ #include <common.h> +#include <command.h> #include <fdtdec.h> #include <linux/libfdt.h> #include <malloc.h> @@ -297,8 +298,8 @@ static int check_carveout(void) return 0; } -static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) +static int do_test_fdtdec(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) { /* basic tests */ CHECKOK(run_test("", "", "")); diff --git a/lib/gunzip.c b/lib/gunzip.c index 9e6ccd692a3..bee3b9261f3 100644 --- a/lib/gunzip.c +++ b/lib/gunzip.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <blk.h> #include <command.h> #include <console.h> #include <div64.h> diff --git a/lib/hashtable.c b/lib/hashtable.c index f82f2463cf2..b96dbe19be4 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -13,6 +13,7 @@ */ #include <errno.h> +#include <log.h> #include <malloc.h> #include <sort.h> @@ -605,7 +606,7 @@ static int match_entry(struct env_entry *ep, int flag, int argc, ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag, char **resp, size_t size, - int argc, char * const argv[]) + int argc, char *const argv[]) { struct env_entry *list[htab->size]; char *res, *p; diff --git a/lib/image-sparse.c b/lib/image-sparse.c index 036062139bb..187ac28cd36 100644 --- a/lib/image-sparse.c +++ b/lib/image-sparse.c @@ -36,11 +36,14 @@ #include <config.h> #include <common.h> +#include <blk.h> #include <image-sparse.h> #include <div64.h> +#include <log.h> #include <malloc.h> #include <part.h> #include <sparse_format.h> +#include <asm/cache.h> #include <linux/math64.h> diff --git a/lib/libavb/avb_cmdline.c b/lib/libavb/avb_cmdline.c index dd859d3467e..cb54e658c48 100644 --- a/lib/libavb/avb_cmdline.c +++ b/lib/libavb/avb_cmdline.c @@ -7,6 +7,7 @@ #include "avb_sha.h" #include "avb_util.h" #include "avb_version.h" +#include <log.h> #include <malloc.h> #define NUM_GUIDS 3 diff --git a/lib/libavb/avb_descriptor.c b/lib/libavb/avb_descriptor.c index 86b8d1b9943..56a3a91fc23 100644 --- a/lib/libavb/avb_descriptor.c +++ b/lib/libavb/avb_descriptor.c @@ -6,6 +6,7 @@ #include "avb_descriptor.h" #include "avb_util.h" #include "avb_vbmeta_image.h" +#include <log.h> #include <malloc.h> bool avb_descriptor_validate_and_byteswap(const AvbDescriptor* src, diff --git a/lib/libavb/avb_slot_verify.c b/lib/libavb/avb_slot_verify.c index 58baf522fcb..ae8e1dffa4c 100644 --- a/lib/libavb/avb_slot_verify.c +++ b/lib/libavb/avb_slot_verify.c @@ -14,6 +14,7 @@ #include "avb_util.h" #include "avb_vbmeta_image.h" #include "avb_version.h" +#include <log.h> #include <malloc.h> /* Maximum number of partitions that can be loaded with avb_slot_verify(). */ diff --git a/lib/libavb/avb_util.c b/lib/libavb/avb_util.c index 94773b77e7e..8719ede15a7 100644 --- a/lib/libavb/avb_util.c +++ b/lib/libavb/avb_util.c @@ -4,6 +4,7 @@ */ #include "avb_util.h" +#include <log.h> #include <malloc.h> #include <stdarg.h> diff --git a/lib/linux_compat.c b/lib/linux_compat.c index 89a6fd6ec96..c83426f59dc 100644 --- a/lib/linux_compat.c +++ b/lib/linux_compat.c @@ -2,6 +2,7 @@ #include <common.h> #include <malloc.h> #include <memalign.h> +#include <asm/cache.h> #include <linux/compat.h> struct p_current cur = { diff --git a/lib/list_sort.c b/lib/list_sort.c index beb7273fd30..58e1e1614a5 100644 --- a/lib/list_sort.c +++ b/lib/list_sort.c @@ -1,4 +1,5 @@ #ifndef __UBOOT__ +#include <log.h> #include <dm/devres.h> #include <linux/kernel.h> #include <linux/module.h> diff --git a/lib/lmb.c b/lib/lmb.c index 07b9308adf2..008bcc7930d 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -7,7 +7,9 @@ */ #include <common.h> +#include <image.h> #include <lmb.h> +#include <log.h> #include <malloc.h> #define LMB_ALLOC_ANYWHERE 0 diff --git a/lib/lzma/LzmaTools.c b/lib/lzma/LzmaTools.c index 2537cb8f8c6..521258e623f 100644 --- a/lib/lzma/LzmaTools.c +++ b/lib/lzma/LzmaTools.c @@ -19,6 +19,7 @@ #include <config.h> #include <common.h> +#include <log.h> #include <watchdog.h> #ifdef CONFIG_LZMA diff --git a/lib/membuff.c b/lib/membuff.c index 45dae2d576f..36dc43a523f 100644 --- a/lib/membuff.c +++ b/lib/membuff.c @@ -8,6 +8,7 @@ #include <common.h> #include <errno.h> +#include <log.h> #include <malloc.h> #include "membuff.h" diff --git a/lib/net_utils.c b/lib/net_utils.c index 8af77829705..0a8a557319c 100644 --- a/lib/net_utils.c +++ b/lib/net_utils.c @@ -10,6 +10,7 @@ */ #include <common.h> +#include <net.h> struct in_addr string_to_ip(const char *s) { diff --git a/lib/of_live.c b/lib/of_live.c index c49e95e38c7..05a45ed34af 100644 --- a/lib/of_live.c +++ b/lib/of_live.c @@ -9,6 +9,7 @@ */ #include <common.h> +#include <log.h> #include <linux/libfdt.h> #include <of_live.h> #include <malloc.h> diff --git a/lib/optee/optee.c b/lib/optee/optee.c index d4355c6d033..e59b5766e72 100644 --- a/lib/optee/optee.c +++ b/lib/optee/optee.c @@ -6,6 +6,7 @@ #include <common.h> #include <image.h> +#include <log.h> #include <malloc.h> #include <linux/libfdt.h> #include <tee/optee.h> diff --git a/lib/panic.c b/lib/panic.c index 8e72c265a61..58382ac4f4c 100644 --- a/lib/panic.c +++ b/lib/panic.c @@ -14,6 +14,7 @@ #if !defined(CONFIG_PANIC_HANG) #include <command.h> #endif +#include <linux/delay.h> static void panic_finish(void) __attribute__ ((noreturn)); diff --git a/lib/physmem.c b/lib/physmem.c index 84b191dae3e..fc90ce4d7cf 100644 --- a/lib/physmem.c +++ b/lib/physmem.c @@ -9,6 +9,7 @@ */ #include <common.h> +#include <log.h> #include <mapmem.h> #include <physmem.h> #include <linux/compiler.h> diff --git a/lib/qsort.c b/lib/qsort.c index f63d4ef7268..2f18588dfcc 100644 --- a/lib/qsort.c +++ b/lib/qsort.c @@ -15,6 +15,7 @@ * calculation, as well as to reduce the generated code size with * bcc and gcc. */ +#include <log.h> #include <linux/types.h> #include <common.h> #include <exports.h> diff --git a/lib/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c index 420ab2eba05..a437cbe26f2 100644 --- a/lib/rsa/rsa-mod-exp.c +++ b/lib/rsa/rsa-mod-exp.c @@ -6,6 +6,7 @@ #ifndef USE_HOSTCC #include <common.h> #include <fdtdec.h> +#include <log.h> #include <asm/types.h> #include <asm/byteorder.h> #include <linux/errno.h> @@ -262,8 +263,8 @@ int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, if (!prop->public_exponent) key.exponent = RSA_DEFAULT_PUBEXP; else - key.exponent = - fdt64_to_cpu(*((uint64_t *)(prop->public_exponent))); + rsa_convert_big_endian((uint32_t *)&key.exponent, + prop->public_exponent, 2); if (!key.len || !prop->modulus || !prop->rr) { debug("%s: Missing RSA key info", __func__); diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index 580c7447093..40ca1e1f573 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -4,7 +4,7 @@ */ #include "mkimage.h" -#include <malloc.h> +#include <stdlib.h> #include <stdio.h> #include <string.h> #include <image.h> @@ -135,9 +135,14 @@ static int rsa_engine_get_pub_key(const char *keydir, const char *name, if (engine_id && !strcmp(engine_id, "pkcs11")) { if (keydir) - snprintf(key_id, sizeof(key_id), - "pkcs11:%s;object=%s;type=public", - keydir, name); + if (strstr(keydir, "object=")) + snprintf(key_id, sizeof(key_id), + "pkcs11:%s;type=public", + keydir); + else + snprintf(key_id, sizeof(key_id), + "pkcs11:%s;object=%s;type=public", + keydir, name); else snprintf(key_id, sizeof(key_id), "pkcs11:object=%s;type=public", @@ -255,9 +260,14 @@ static int rsa_engine_get_priv_key(const char *keydir, const char *name, if (engine_id && !strcmp(engine_id, "pkcs11")) { if (keydir) - snprintf(key_id, sizeof(key_id), - "pkcs11:%s;object=%s;type=private", - keydir, name); + if (strstr(keydir, "object=")) + snprintf(key_id, sizeof(key_id), + "pkcs11:%s;type=private", + keydir); + else + snprintf(key_id, sizeof(key_id), + "pkcs11:%s;object=%s;type=private", + keydir, name); else snprintf(key_id, sizeof(key_id), "pkcs11:object=%s;type=private", diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 80e817314b5..1d55b997e34 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -6,6 +6,7 @@ #ifndef USE_HOSTCC #include <common.h> #include <fdtdec.h> +#include <log.h> #include <malloc.h> #include <asm/types.h> #include <asm/byteorder.h> @@ -445,7 +446,7 @@ static int rsa_verify_with_keynode(struct image_sign_info *info, prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL); - if (!prop.num_bits || !prop.modulus) { + if (!prop.num_bits || !prop.modulus || !prop.rr) { debug("%s: Missing RSA key info", __func__); return -EFAULT; } diff --git a/lib/slre.c b/lib/slre.c index 969c46a8591..e82a9e7635b 100644 --- a/lib/slre.c +++ b/lib/slre.c @@ -20,6 +20,7 @@ #include <stdlib.h> #include <string.h> #else +#include <log.h> #include <common.h> #include <linux/ctype.h> #endif /* SLRE_TEST */ diff --git a/lib/time.c b/lib/time.c index 75de48f9003..65db0f6cda2 100644 --- a/lib/time.c +++ b/lib/time.c @@ -5,13 +5,16 @@ */ #include <common.h> +#include <bootstage.h> #include <dm.h> #include <errno.h> +#include <init.h> #include <time.h> #include <timer.h> #include <watchdog.h> #include <div64.h> #include <asm/io.h> +#include <linux/delay.h> #ifndef CONFIG_WD_PERIOD # define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */ @@ -181,7 +184,7 @@ void udelay(unsigned long usec) do { WATCHDOG_RESET(); kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec; - __udelay (kv); + __udelay(kv); usec -= kv; } while(usec); } diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index 1138c7012ae..8fc7e48d994 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -242,6 +242,7 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) goto abort; case 'u': case 'd': + case 'i': div = 1000000000; if (islong) { num = va_arg(va, unsigned long); @@ -251,7 +252,7 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) num = va_arg(va, unsigned int); } - if (ch == 'd') { + if (ch != 'u') { if (islong && (long)num < 0) { num = -(long)num; out(info, '-'); diff --git a/lib/tpm-common.c b/lib/tpm-common.c index 86b4f413c2e..e4af87f76aa 100644 --- a/lib/tpm-common.c +++ b/lib/tpm-common.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> +#include <log.h> #include <asm/unaligned.h> #include <tpm-common.h> #include "tpm-utils.h" diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c index b4498e6afc7..a846fe00dd3 100644 --- a/lib/tpm-v1.c +++ b/lib/tpm-v1.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> +#include <log.h> #include <asm/unaligned.h> #include <u-boot/sha1.h> #include <tpm-common.h> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index f89592d6e2f..5a039f65d13 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -8,6 +8,7 @@ #include <dm.h> #include <tpm-common.h> #include <tpm-v2.h> +#include <linux/bitops.h> #include "tpm-utils.h" u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode) diff --git a/lib/uuid.c b/lib/uuid.c index c1cb9df6aac..e62d5ca2643 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -4,8 +4,11 @@ */ #include <common.h> +#include <command.h> #include <env.h> +#include <rand.h> #include <time.h> +#include <uuid.h> #include <linux/ctype.h> #include <errno.h> #include <common.h> @@ -284,7 +287,7 @@ void gen_rand_uuid_str(char *uuid_str, int str_format) } #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CMD_UUID) -int do_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_uuid(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { char uuid[UUID_STR_LEN + 1]; int str_format; diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b4edee29b0d..de9ef902b96 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -19,6 +19,7 @@ #include <div64.h> #include <hexdump.h> #include <stdarg.h> +#include <uuid.h> #include <vsprintf.h> #include <linux/ctype.h> #include <linux/err.h> |