diff --git a/README.md b/README.md
index 85d495a1..433785d3 100644
--- a/README.md
+++ b/README.md
@@ -370,6 +370,16 @@ Please see the [utasker/README.md](utasker/README.md) for further usage and
details.
+
+
+#### UEFI (wolfCrypt UEFI application Example)
+
+This directory contains an example UEFI application that runs wolfcrypt test.
+
+Please see the [uefi/README.md](uefi/README.md) for further usage and
+details.
+
+
## Notes
diff --git a/uefi/Makefile b/uefi/Makefile
new file mode 100644
index 00000000..83f921be
--- /dev/null
+++ b/uefi/Makefile
@@ -0,0 +1,53 @@
+BUILD_DIR=./build
+CRYPTO_SRC=./wolfssl/wolfcrypt/src
+WOLFSSL_REPO=https://github.com/wolfSSL/wolfssl
+CFLAGS=-fpie -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -static-libgcc -nostdlib
+# enable user settings
+CFLAGS+= -DWOLFSSL_USER_SETTINGS
+CFLAGS+=-I./wolfssl/ -I. -I/usr/include/efi
+CFLAGS+=-ggdb
+CC=gcc
+LD=ld
+LDFLAGS_START=-static -pie --no-dynamic-linker -Bsymbolic -L/usr/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/ -Lgnu-efi-dir/x86_64/gnuefi -T/usr/lib/elf_x86_64_efi.lds /usr/lib/crt0-efi-x86_64.o $(LDFLAGS)
+LDFLAGS_END=-lgnuefi -lefi -lgcc
+
+_OBJS=sha256.o sha3.o misc.o coding.o hmac.o rsa.o random.o wolfmath.o \
+ integer.o tfm.o asm.o cpuid.o memory.o logging.o wc_port.o asn.o hash.o \
+ main.o test.o error.o string.o aes.o wc_encrypt.o
+
+OBJS=$(addprefix $(BUILD_DIR)/,$(_OBJS))
+
+$(shell mkdir -p $(BUILD_DIR))
+
+all: wolfcrypt.efi
+
+.PHONY: clone_repo
+
+clone_repo:
+ @if [ ! -d $(CRYPTO_SRC) ]; then \
+ git clone $(WOLFSSL_REPO); \
+ fi
+
+create_build_dir:
+ @if [ ! -d $(BUILD_DIR) ]; then mkdir $(BUILD_DIR); fi
+
+$(BUILD_DIR)/wolfcrypt.elf: clone_repo $(OBJS)
+ $(LD) $(LDFLAGS_START) $(OBJS) -o $(BUILD_DIR)/wolfcrypt.elf $(LDFLAGS_END)
+
+wolfcrypt.efi: $(BUILD_DIR)/wolfcrypt.elf
+ objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 $(BUILD_DIR)/wolfcrypt.elf wolfcrypt.efi
+
+$(BUILD_DIR)/test.o: $(CRYPTO_SRC)/../test/test.c
+ $(CC) $(CFLAGS) -c $? -o $@
+
+$(BUILD_DIR)/main.o: main.c
+ $(CC) $(CFLAGS) -c $? -o $@
+
+$(BUILD_DIR)/string.o: string.c
+ $(CC) $(CFLAGS) -c $? -o $@
+
+$(BUILD_DIR)/%.o: $(CRYPTO_SRC)/%.c
+ $(CC) $(CFLAGS) -c $? -o $@
+
+clean:
+ rm -rf $(BUILD_DIR) wolfcrypt.efi
diff --git a/uefi/README.md b/uefi/README.md
new file mode 100644
index 00000000..4e467b1a
--- /dev/null
+++ b/uefi/README.md
@@ -0,0 +1,96 @@
+wolfcrypt UEFI Example Applications
+===================================
+
+Requires gnu-efi. Tested with qemu and OVFM UEFI implementation. It uses a
+custom implementation for string.h functions (`string.c`) based on wolfBoot
+`src/string.c`. You can customize the build by changing `user_settings.h` and
+adding the relevant `.o` file into the Makefile `_OBJS` variable.
+
+# Compile
+
+## Pre-requisites
+
+```
+git make gcc gnu-efi
+```
+
+## build
+
+```
+make
+
+```
+
+# Test on qemu
+
+## Pre-requisites
+```
+dosfstools qemu qemu-system-x86 ovmf
+```
+## Create efi disk
+
+We need to create a FAT partition to store efi application.
+
+```
+dd if=/dev/zero of=./efi.disk bs=256M count=1
+sudo mkfs.vfat ./efi.disk
+```
+
+Move wolfcrypt.efi and startup.nsh into the fat32 partition
+```
+mkdir -p /tmp/efi
+sudo mount ./efi.disk /tmp/efi -oloop
+sudo cp wolfcrypt.efi /tmp/efi
+sudo cp startup.nsh /tmp/efi
+sudo umount /tmp/efi
+```
+
+## Run qemu
+
+```
+qemu-system-x86_64 -bios /path/to/OVMF.fd -display none -serial stdio -net none -m 256M -drive file=./efi.disk,index=0,media=disk,format=raw
+```
+
+/path/to/OVMF.fd may be /usr/share/edk2-ovmf/x64 or /usr/share/qemu
+
+## Example output
+
+```
+UEFI Interactive Shell v2.2
+EDK II
+UEFI v2.70 (EDK II, 0x00010000)
+Mapping table
+ FS0: Alias(s):F0a:;BLK0:
+ PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
+ BLK1: Alias(s):
+ PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)
+Press ESC in 1 seconds to skip startup.nsh or any other key to continue.
+Shell> fs0:
+FS0:\> wolfcrypt.efi
+status: 0x0
+Image base: 0xE15E000
+------------------------------------------------------------------------------
+ wolfSSL version ⸵⸶6
+------------------------------------------------------------------------------
+error test passed!
+MEMORY test passed!
+base64 test passed!
+asn test passed!
+RANDOM test passed!
+SHA-256 test passed!
+SHA-3 test passed!
+SHAKE128 test passed!
+SHAKE256 test passed!
+Hash test passed!
+HMAC-SHA256 test passed!
+HMAC-SHA3 test passed!
+AES test passed!
+AES192 test passed!
+AES256 test passed!
+RSA test passed!
+logging test passed!
+mutex test passed!
+Test complete
+ret: 0
+FS0:\>
+```
diff --git a/uefi/main.c b/uefi/main.c
new file mode 100644
index 00000000..6eef1b4b
--- /dev/null
+++ b/uefi/main.c
@@ -0,0 +1,107 @@
+
+#include
+#include
+#include
+#include
+#include
+
+#define STR_SIZE 512
+
+#ifndef WAIT_FOR_GDB
+#define WAIT_FOR_GDB 0
+#endif
+
+#define uefi_printf(_f_, ...) Print(L##_f_, ##__VA_ARGS__)
+
+void char8_to_char16(const char* str8, wchar_t* str16)
+{
+ size_t i;
+ size_t size_str8 = strlen(str8);
+ for (i = 0; i < size_str8; ++i) {
+ str16[i] = (wchar_t)str8[i];
+ }
+ str16[i] = '\0';
+}
+
+void logging_cb(const int logLevel, const char *const logMessage)
+{
+ wchar_t str16[STR_SIZE];
+ char8_to_char16(logMessage, str16);
+ uefi_printf("%s", str16);
+}
+
+void *XMALLOC(size_t n, void* heap, int type)
+{
+ return AllocateZeroPool(n);
+}
+
+void *XREALLOC(void *p, size_t n, void* heap, int type)
+{
+ FreePool(p);
+ p = NULL;
+ return AllocateZeroPool(n);
+}
+
+void XFREE(void *p, void* heap, int type)
+{
+ return FreePool(p);
+}
+
+/* TODO: remove dependencies in random.c to open/read/close */
+int open (const char *__file, int __oflag)
+{
+ uefi_printf("open\n");
+ return -1;
+}
+
+ssize_t read (int __fd, void *__buf, size_t __nbytes)
+{
+ uefi_printf("read\n");
+ return -1;
+}
+
+int close(int __fd)
+{
+ uefi_printf("close\n");
+ return -1;
+}
+
+EFI_STATUS
+EFIAPI
+efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_LOADED_IMAGE *loaded_image = NULL;
+ volatile int debug = 1;
+ EFI_STATUS status;
+ int ret;
+
+ InitializeLib(ImageHandle, SystemTable);
+ wolfSSL_Debugging_ON();
+ wolfSSL_SetLoggingCb(logging_cb);
+
+ status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol,
+ 3,
+ ImageHandle,
+ &LoadedImageProtocol,
+ (void **)&loaded_image);
+ Print(L"status: 0x%lx\n", status);
+ Print(L"Image base: 0x%lx\n", loaded_image->ImageBase);
+
+#if WAIT_FOR_GDB
+ /* to debug from gdb:
+ *
+ * 1. run qemu with -s option. Take note of Image base value printed by the
+ * app.
+ * 2. run gdb, use command: symbol-file wolfcrypt.elf -o $image_base
+ * with image based value from the print above.
+ * 3. set variable debug = 0 to exit the loop and continue the debugging */
+ while(debug) {};
+#else
+ (void)debug;
+#endif
+
+ ret = wolfcrypt_test(NULL);
+ Print(L"ret: %d\n", ret);
+
+ return EFI_SUCCESS;
+}
diff --git a/uefi/startup.nsh b/uefi/startup.nsh
new file mode 100644
index 00000000..26fd77a4
--- /dev/null
+++ b/uefi/startup.nsh
@@ -0,0 +1,2 @@
+fs0:
+wolfcrypt.efi
diff --git a/uefi/string.c b/uefi/string.c
new file mode 100644
index 00000000..40cc4e53
--- /dev/null
+++ b/uefi/string.c
@@ -0,0 +1,227 @@
+/* string.c
+ *
+ * Implementations of standard library functions to eliminate external dependencies.
+ *
+ *
+ * Copyright (C) 2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSLL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include
+#include
+
+int islower(int c)
+{
+ return (c >= 'a' && c <= 'z');
+}
+
+int isupper(int c)
+{
+ return (c >= 'A' && c <= 'Z');
+}
+
+int tolower(int c)
+{
+ return isupper(c) ? c - 'A' + 'a' : c;
+}
+
+int toupper(int c)
+{
+ return islower(c) ? c - 'a' + 'A' : c;
+}
+
+int isalpha(int c)
+{
+ return (isupper(c) || islower(c));
+}
+
+char *strcat(char *dest, const char *src)
+{
+ size_t i = 0;
+ size_t j = strlen(dest);
+
+ for (i = 0; i < strlen(src); i++) {
+ dest[j++] = src[i];
+ }
+ dest[j] = '\0';
+
+ return dest;
+}
+
+int strcmp(const char *s1, const char *s2)
+{
+ int diff = 0;
+
+ while (!diff && *s1) {
+ diff = (int)*s1 - (int)*s2;
+ s1++;
+ s2++;
+ }
+
+ return diff;
+}
+
+int strcasecmp(const char *s1, const char *s2)
+{
+ int diff = 0;
+
+ while (!diff && *s1) {
+ diff = (int)*s1 - (int)*s2;
+
+ if ((diff == 'A' - 'a') || (diff == 'a' - 'A'))
+ diff = 0;
+
+ s1++;
+ s2++;
+ }
+
+ return diff;
+}
+
+int strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ int diff = 0;
+ size_t i = 0;
+
+ while (!diff && *s1) {
+ diff = (int)*s1 - (int)*s2;
+
+ if ((diff == 'A' - 'a') || (diff == 'a' - 'A'))
+ diff = 0;
+
+ s1++;
+ s2++;
+ if (++i > n)
+ break;
+ }
+ return diff;
+}
+
+char *strncat(char *dest, const char *src, size_t n)
+{
+ size_t i = 0;
+ size_t j = strlen(dest);
+
+ for (i = 0; i < strlen(src); i++) {
+ if (j >= (n - 1)) {
+ break;
+ }
+ dest[j++] = src[i];
+ }
+ dest[j] = '\0';
+
+ return dest;
+}
+
+int strncmp(const char *s1, const char *s2, size_t n)
+{
+ int diff = 0;
+
+ while (n > 0) {
+ diff = (unsigned char)*s1 - (unsigned char)*s2;
+ if (diff || !*s1)
+ break;
+ s1++;
+ s2++;
+ n--;
+ }
+
+ return diff;
+}
+
+char *strncpy(char *dst, const char *src, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ dst[i] = src[i];
+ if (src[i] == '\0')
+ break;
+ }
+
+ return dst;
+}
+
+char *strcpy(char *dst, const char *src)
+{
+ size_t i = 0;
+
+ while(1) {
+ dst[i] = src[i];
+ if (src[i] == '\0')
+ break;
+ i++;
+ }
+
+ return dst;
+}
+
+int memcmp(const void *_s1, const void *_s2, size_t n)
+{
+ int diff = 0;
+ const unsigned char *s1 = (const unsigned char *)_s1;
+ const unsigned char *s2 = (const unsigned char *)_s2;
+
+ while (!diff && n) {
+ diff = (int)*s1 - (int)*s2;
+ s1++;
+ s2++;
+ n--;
+ }
+
+ return diff;
+}
+
+void* memchr(void const *s, int c_in, size_t n)
+{
+ unsigned char c = (unsigned char)c_in;
+ unsigned char *char_ptr = (unsigned char*)s;
+ for (; n > 0; --n, ++char_ptr) {
+ if (*char_ptr == c) {
+ return (void*)char_ptr;
+ }
+ }
+ return NULL;
+}
+
+size_t strlen(const char *s)
+{
+ size_t i = 0;
+
+ while (s[i] != 0)
+ i++;
+
+ return i;
+}
+
+void *memmove(void *dst, const void *src, size_t n)
+{
+ int i;
+ if (dst == src)
+ return dst;
+ if (src < dst) {
+ const char *s = (const char *)src;
+ char *d = (char *)dst;
+ for (i = n - 1; i >= 0; i--) {
+ d[i] = s[i];
+ }
+ return dst;
+ } else {
+ return memcpy(dst, src, n);
+ }
+}
diff --git a/uefi/user_settings.h b/uefi/user_settings.h
new file mode 100644
index 00000000..257f8020
--- /dev/null
+++ b/uefi/user_settings.h
@@ -0,0 +1,24 @@
+#define WOLFCRYPT_ONLY
+#define HAVE_ENTROPY_MEMUSE
+#define ENTROPY_MEMUSE_FORCE_FAILURE
+#define USE_FAST_MATH
+#define FP_MAX_BITS 8192
+#define WOLFSSL_SHA3
+#define HAVE_HASHDRBG
+#define SINGLE_THREADED
+#define XMALLOC_USER
+#define NO_MD5
+#define NO_SHA
+#define NO_PKCS8
+#define NO_PKCS12
+#define NO_DSA
+#define NO_ASN_TIME
+#define NO_FILESYSTEM
+#define NO_INLINE
+#define NO_DH
+#define NO_DES3
+#define NO_MD4
+#define NO_SIG_WRAPPER
+#define NO_PWDBASED
+#define NO_ERROR_STRINGS
+#define XPRINTF(_f_, ...) Print(L##_f_, ##__VA_ARGS__)