[gbl] Implement software-based EFI_RNG_PROTOCOL

Implement a software-based EFI_RNG_PROTOCOL using a Pseudo-Random
Number Generator (LCG) seeded by the system timer. This is used
when CONFIG_EFI_RNG_PROTOCOL (hardware-based) is disabled, satisfying
GBL's requirement for generating stack canaries.

TAG=agy
CONV=236c2e4e-69e4-48b6-a8ea-8986bc68bb04

Change-Id: I0b00e0b37ef168d57111060a1454b449920784f5
Reviewed-on: https://turquoise-internal-review.googlesource.com/c/third_party/u-boot/+/1369888
Reviewed-by: David Pursell <dpursell@google.com>
Commit-Queue: Sergii Parubochyi <sergiip@google.com>
GitOrigin-RevId: ffe301df3f23f90350c526c9464eb37de022d887
diff --git a/board/khadas/Kconfig b/board/khadas/Kconfig
index 34b9c8a..98db604 100644
--- a/board/khadas/Kconfig
+++ b/board/khadas/Kconfig
@@ -42,3 +42,12 @@
 source "board/khadas/kvim2/Kconfig"
 endif
 
+# Note: EFI_RNG_NON_SECURE_SW_PROTOCOL is defined here because lib/efi_loader/Kconfig
+# is not processed by the build system in this U-Boot fork.
+config EFI_RNG_NON_SECURE_SW_PROTOCOL
+  bool "Software EFI_RNG_PROTOCOL support"
+  depends on !EFI_RNG_PROTOCOL
+  default n
+  help
+    Provide a software-based EFI_RNG_PROTOCOL implementation.
+
diff --git a/board/khadas/defconfigs/kvim3_zircon_defconfig b/board/khadas/defconfigs/kvim3_zircon_defconfig
index 7dc84e5..c5eca17 100644
--- a/board/khadas/defconfigs/kvim3_zircon_defconfig
+++ b/board/khadas/defconfigs/kvim3_zircon_defconfig
@@ -9,3 +9,4 @@
 CONFIG_AUTOBOOT_KEYED=y
 CONFIG_AUTOBOOT_STOP_STR="f"
 CONFIG_ZIRCON_VERIFIED_BOOT=y
+CONFIG_EFI_RNG_NON_SECURE_SW_PROTOCOL=y
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 525a8ec..17f2175 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -580,6 +580,7 @@
 /* Called by efi_init_obj_list() to install EFI_ANDROID_BOOT_PROTOCOL */
 efi_status_t efi_android_boot_register(void);
 efi_status_t efi_gbl_fastboot_transport_register(void);
+efi_status_t efi_rng_sw_register(void);
 /* Called by efi_init_obj_list() to do initial measurement */
 efi_status_t efi_tcg2_do_initial_measurement(void);
 /* measure the pe-coff image, extend PCR and add Event Log */
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 09f51ac..4d6d1ca 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -83,6 +83,7 @@
 obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o
 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
 obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
+obj-$(CONFIG_EFI_RNG_NON_SECURE_SW_PROTOCOL) += efi_rng_sw.o
 obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_tcg2.o
 obj-$(CONFIG_EFI_RISCV_BOOT_PROTOCOL) += efi_riscv.o
 obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o
diff --git a/lib/efi_loader/efi_rng_sw.c b/lib/efi_loader/efi_rng_sw.c
new file mode 100644
index 0000000..fd8d32a
--- /dev/null
+++ b/lib/efi_loader/efi_rng_sw.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2026 The Fuchsia Authors
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ */
+
+/*
+ * WARNING: This is a software-based pseudo-random number generator (PRNG)
+ * intended ONLY for development and debugging. It uses U-Boot's native
+ * rand() which is NOT cryptographically secure.
+ *
+ * DO NOT use this implementation in production environments or for security-
+ * sensitive applications (e.g. key generation, cryptography).
+ */
+
+#include <common.h>
+#include <efi_loader.h>
+#include <efi_rng.h>
+
+static const efi_guid_t rng_raw_guid = EFI_RNG_ALGORITHM_RAW;
+
+static efi_status_t EFIAPI rng_getinfo(struct efi_rng_protocol *this,
+				       efi_uintn_t *rng_algorithm_list_size,
+				       efi_guid_t *rng_algorithm_list)
+{
+	EFI_ENTRY("%p, %p, %p", this, rng_algorithm_list_size,
+		  rng_algorithm_list);
+
+	if (!this || !rng_algorithm_list_size)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (!rng_algorithm_list ||
+	    *rng_algorithm_list_size < sizeof(*rng_algorithm_list)) {
+		*rng_algorithm_list_size = sizeof(*rng_algorithm_list);
+		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+	}
+
+	*rng_algorithm_list_size = sizeof(*rng_algorithm_list);
+	guidcpy(rng_algorithm_list, &rng_raw_guid);
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+/*
+ * WARNING: U-Boot's rand() is a simple LCG and is NOT cryptographically
+ * secure. This is strictly for development and debugging.
+ *
+ * DO NOT use this implementation in production environments or for security-
+ * sensitive applications.
+ */
+static efi_status_t EFIAPI getrng(struct efi_rng_protocol *this,
+				  efi_guid_t *rng_algorithm,
+				  efi_uintn_t rng_value_length,
+				  uint8_t *rng_value)
+{
+	EFI_ENTRY("%p, %p, %zu, %p", this, rng_algorithm, rng_value_length,
+		  rng_value);
+
+	if (!this || !rng_value || !rng_value_length)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (rng_algorithm) {
+		if (guidcmp(rng_algorithm, &rng_raw_guid))
+			return EFI_EXIT(EFI_UNSUPPORTED);
+	}
+
+	for (efi_uintn_t i = 0; i < rng_value_length; i++) {
+		rng_value[i] = rand() & 0xff;
+	}
+
+	return EFI_EXIT(EFI_SUCCESS);
+}
+
+static const struct efi_rng_protocol efi_rng_protocol = {
+	.get_info = rng_getinfo,
+	.get_rng = getrng,
+};
+
+const efi_guid_t efi_guid_rng_protocol = EFI_RNG_PROTOCOL_GUID;
+
+efi_status_t efi_rng_sw_register(void)
+{
+	efi_status_t ret;
+
+	printf("\n*****************************************************************\n");
+	printf("WARNING: Registering a SOFTWARE-BASED (INSECURE) EFI RNG Protocol!\n");
+	printf("This is ONLY for development and debugging. DO NOT use in production!\n");
+	printf("*****************************************************************\n\n");
+
+	srand(timer_get_us());
+
+	ret = efi_add_protocol(efi_root, &efi_guid_rng_protocol,
+			       (void *)&efi_rng_protocol);
+	if (ret != EFI_SUCCESS)
+		printf("Cannot install software EFI_RNG_PROTOCOL\n");
+
+	return ret;
+}
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 22337b3..1bdb868 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -298,6 +298,11 @@
 		if (ret != EFI_SUCCESS)
 			goto out;
 	}
+	if (IS_ENABLED(CONFIG_EFI_RNG_NON_SECURE_SW_PROTOCOL)) {
+		ret = efi_rng_sw_register();
+		if (ret != EFI_SUCCESS)
+			goto out;
+	}
 
 	if (IS_ENABLED(CONFIG_EFI_RISCV_BOOT_PROTOCOL)) {
 		ret = efi_riscv_register();