seed = early_memremap(efi_rng_seed, sizeof(*seed));
                if (seed != NULL) {
-                       size = min(seed->size, EFI_RANDOM_SEED_SIZE);
+                       size = min_t(u32, seed->size, SZ_1K); // sanity check
                        early_memunmap(seed, sizeof(*seed));
                } else {
                        pr_err("Could not map UEFI random seed!\n");
                        seed = early_memremap(efi_rng_seed,
                                              sizeof(*seed) + size);
                        if (seed != NULL) {
-                               pr_notice("seeding entropy pool\n");
                                add_bootloader_randomness(seed->bits, size);
+                               memzero_explicit(seed->bits, size);
                                early_memunmap(seed, sizeof(*seed) + size);
                        } else {
                                pr_err("Could not map UEFI random seed!\n");
 
        efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
        efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
        efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
+       struct linux_efi_random_seed *prev_seed, *seed = NULL;
+       int prev_seed_size = 0, seed_size = EFI_RANDOM_SEED_SIZE;
        efi_rng_protocol_t *rng = NULL;
-       struct linux_efi_random_seed *seed = NULL;
        efi_status_t status;
 
        status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
        if (status != EFI_SUCCESS)
                return status;
 
+       /*
+        * Check whether a seed was provided by a prior boot stage. In that
+        * case, instead of overwriting it, let's create a new buffer that can
+        * hold both, and concatenate the existing and the new seeds.
+        * Note that we should read the seed size with caution, in case the
+        * table got corrupted in memory somehow.
+        */
+       prev_seed = get_efi_config_table(LINUX_EFI_RANDOM_SEED_TABLE_GUID);
+       if (prev_seed && prev_seed->size <= 512U) {
+               prev_seed_size = prev_seed->size;
+               seed_size += prev_seed_size;
+       }
+
        /*
         * Use EFI_ACPI_RECLAIM_MEMORY here so that it is guaranteed that the
         * allocation will survive a kexec reboot (although we refresh the seed
         * beforehand)
         */
        status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
-                            sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
+                            struct_size(seed, bits, seed_size),
                             (void **)&seed);
-       if (status != EFI_SUCCESS)
-               return status;
+       if (status != EFI_SUCCESS) {
+               efi_warn("Failed to allocate memory for RNG seed.\n");
+               goto err_warn;
+       }
 
        status = efi_call_proto(rng, get_rng, &rng_algo_raw,
-                                EFI_RANDOM_SEED_SIZE, seed->bits);
+                               EFI_RANDOM_SEED_SIZE, seed->bits);
 
        if (status == EFI_UNSUPPORTED)
                /*
        if (status != EFI_SUCCESS)
                goto err_freepool;
 
-       seed->size = EFI_RANDOM_SEED_SIZE;
+       seed->size = seed_size;
+       if (prev_seed_size)
+               memcpy(seed->bits + EFI_RANDOM_SEED_SIZE, prev_seed->bits,
+                      prev_seed_size);
+
        status = efi_bs_call(install_configuration_table, &rng_table_guid, seed);
        if (status != EFI_SUCCESS)
                goto err_freepool;
 
+       if (prev_seed_size) {
+               /* wipe and free the old seed if we managed to install the new one */
+               memzero_explicit(prev_seed->bits, prev_seed_size);
+               efi_bs_call(free_pool, prev_seed);
+       }
        return EFI_SUCCESS;
 
 err_freepool:
+       memzero_explicit(seed, struct_size(seed, bits, seed_size));
        efi_bs_call(free_pool, seed);
+       efi_warn("Failed to obtain seed from EFI_RNG_PROTOCOL\n");
+err_warn:
+       if (prev_seed)
+               efi_warn("Retaining bootloader-supplied seed only");
        return status;
 }