[efi] Retry calls to GetRNG() as needed

The UEFI specification allows GetRNG() to return EFI_NOT_READY, which
is not a particularly helpful error status since there is nothing that
can sensibly be done except to retry immediately.

Retry failed calls to GetRNG() up to a maximum number of attempts.

Debugged-by: Stoo Davies <sdavies@nvidia.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-12-11 14:04:10 +00:00
parent fb1188936c
commit 86c40a8b1e

View File

@@ -54,6 +54,15 @@ EFI_REQUEST_PROTOCOL ( EFI_RNG_PROTOCOL, &efirng );
*/
#define EFIRNG_LEN 32
/** Maximum number of times to attempting requesting data from RNG
*
* The UEFI spec allows GetRNG() to return EFI_NOT_READY, which is not
* a particularly helpful error status since there is nothing that can
* sensibly be done except to retry immediately. We retry failed
* calls to GetRNG() (for any reason) up to this number of times.
*/
#define EFIRNG_MAX_RETRY 16
/**
* Enable entropy gathering
*
@@ -85,29 +94,35 @@ static int efirng_enable ( void ) {
*/
static int efirng_get_noise ( noise_sample_t *noise ) {
uint8_t buf[EFIRNG_LEN];
unsigned int i;
EFI_STATUS efirc;
int rc;
/* Sanity check */
assert ( efirng != NULL );
/* Get the minimum allowed number of random bytes */
if ( ( efirc = efirng->GetRNG ( efirng, NULL, sizeof ( buf ),
buf ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( &efirng, "ENTROPY could not read from RNG: %s\n",
strerror ( rc ) );
return rc;
/* Get random bytes, retrying if needed */
for ( i = 0 ; i < EFIRNG_MAX_RETRY ; i++ ) {
/* Get the minimum allowed number of random bytes */
if ( ( efirc = efirng->GetRNG ( efirng, NULL, sizeof ( buf ),
buf ) ) != 0 ) {
rc = -EEFI ( efirc );
continue;
}
/* Reduce random bytes to a single noise sample. This
* seems like overkill, but we have no way of knowing
* how much entropy is actually present in the bytes
* returned by the RNG protocol.
*/
*noise = crc32_le ( 0, buf, sizeof ( buf ) );
return 0;
}
/* Reduce random bytes to a single noise sample. This seems
* like overkill, but we have no way of knowing how much
* entropy is actually present in the bytes returned by the
* RNG protocol.
*/
*noise = crc32_le ( 0, buf, sizeof ( buf ) );
return 0;
DBGC ( &efirng, "ENTROPY could not read from RNG: %s\n",
strerror ( rc ) );
return rc;
}
/** EFI random number generator protocol entropy source */