0001
0002
0003
0004
0005
0006 #include <linux/efi.h>
0007 #include <asm/efi.h>
0008
0009 #include "efistub.h"
0010
0011 typedef union efi_rng_protocol efi_rng_protocol_t;
0012
0013 union efi_rng_protocol {
0014 struct {
0015 efi_status_t (__efiapi *get_info)(efi_rng_protocol_t *,
0016 unsigned long *,
0017 efi_guid_t *);
0018 efi_status_t (__efiapi *get_rng)(efi_rng_protocol_t *,
0019 efi_guid_t *, unsigned long,
0020 u8 *out);
0021 };
0022 struct {
0023 u32 get_info;
0024 u32 get_rng;
0025 } mixed_mode;
0026 };
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 efi_status_t efi_get_random_bytes(unsigned long size, u8 *out)
0040 {
0041 efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
0042 efi_status_t status;
0043 efi_rng_protocol_t *rng = NULL;
0044
0045 status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
0046 if (status != EFI_SUCCESS)
0047 return status;
0048
0049 return efi_call_proto(rng, get_rng, NULL, size, out);
0050 }
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 efi_status_t efi_random_get_seed(void)
0066 {
0067 efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
0068 efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
0069 efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
0070 efi_rng_protocol_t *rng = NULL;
0071 struct linux_efi_random_seed *seed = NULL;
0072 efi_status_t status;
0073
0074 status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
0075 if (status != EFI_SUCCESS)
0076 return status;
0077
0078 status = efi_bs_call(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
0079 sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
0080 (void **)&seed);
0081 if (status != EFI_SUCCESS)
0082 return status;
0083
0084 status = efi_call_proto(rng, get_rng, &rng_algo_raw,
0085 EFI_RANDOM_SEED_SIZE, seed->bits);
0086
0087 if (status == EFI_UNSUPPORTED)
0088
0089
0090
0091
0092 status = efi_call_proto(rng, get_rng, NULL,
0093 EFI_RANDOM_SEED_SIZE, seed->bits);
0094
0095 if (status != EFI_SUCCESS)
0096 goto err_freepool;
0097
0098 seed->size = EFI_RANDOM_SEED_SIZE;
0099 status = efi_bs_call(install_configuration_table, &rng_table_guid, seed);
0100 if (status != EFI_SUCCESS)
0101 goto err_freepool;
0102
0103 return EFI_SUCCESS;
0104
0105 err_freepool:
0106 efi_bs_call(free_pool, seed);
0107 return status;
0108 }