VirtualBox

Ignore:
Timestamp:
Mar 31, 2025 11:31:09 AM (2 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168237
Message:

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

Location:
trunk/src/VBox/Devices/EFI/FirmwareNew
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/EFI/FirmwareNew

  • trunk/src/VBox/Devices/EFI/FirmwareNew/MdePkg/Library/BaseRngLib/Rand/RdRand.c

    r105670 r108794  
    33  to provide high-quality random numbers.
    44
     5Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
    56Copyright (c) 2023, Arm Limited. All rights reserved.<BR>
     7Copyright (c) 2022, Pedro Falcato. All rights reserved.<BR>
    68Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
    79Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
     
    2325#define RDRAND_MASK  BIT30
    2426
    25 STATIC BOOLEAN  mRdRandSupported;
     27//
     28// Intel SDM says 10 tries is good enough for reliable RDRAND usage.
     29//
     30#define RDRAND_RETRIES  10
     31
     32#define RDRAND_TEST_SAMPLES  8
     33
     34#define RDRAND_MIN_CHANGE  5
     35
     36//
     37// Add a define for native-word RDRAND, just for the test.
     38//
     39#ifdef MDE_CPU_X64
     40#define ASM_RDRAND  AsmRdRand64
     41#else
     42#define ASM_RDRAND  AsmRdRand32
     43#endif
     44
     45/**
     46  Tests RDRAND for broken implementations.
     47
     48  @retval TRUE         RDRAND is reliable (and hopefully safe).
     49  @retval FALSE        RDRAND is unreliable and should be disabled, despite CPUID.
     50
     51**/
     52STATIC
     53BOOLEAN
     54TestRdRand (
     55  VOID
     56  )
     57{
     58  //
     59  // Test for notoriously broken rdrand implementations that always return the same
     60  // value, like the Zen 3 uarch (all-1s) or other several AMD families on suspend/resume (also all-1s).
     61  // Note that this should be expanded to extensively test for other sorts of possible errata.
     62  //
     63
     64  //
     65  // Our algorithm samples rdrand $RDRAND_TEST_SAMPLES times and expects
     66  // a different result $RDRAND_MIN_CHANGE times for reliable RDRAND usage.
     67  //
     68  UINTN   Prev;
     69  UINT8   Idx;
     70  UINT8   TestIteration;
     71  UINT32  Changed;
     72
     73  Changed = 0;
     74
     75  for (TestIteration = 0; TestIteration < RDRAND_TEST_SAMPLES; TestIteration++) {
     76    UINTN  Sample;
     77    //
     78    // Note: We use a retry loop for rdrand. Normal users get this in BaseRng.c
     79    // Any failure to get a random number will assume RDRAND does not work.
     80    //
     81    for (Idx = 0; Idx < RDRAND_RETRIES; Idx++) {
     82      if (ASM_RDRAND (&Sample)) {
     83        break;
     84      }
     85    }
     86
     87    if (Idx == RDRAND_RETRIES) {
     88      DEBUG ((DEBUG_ERROR, "BaseRngLib/x86: CPU BUG: Failed to get an RDRAND random number - disabling\n"));
     89      return FALSE;
     90    }
     91
     92    if (TestIteration != 0) {
     93      Changed += Sample != Prev;
     94    }
     95
     96    Prev = Sample;
     97  }
     98
     99  if (Changed < RDRAND_MIN_CHANGE) {
     100    DEBUG ((DEBUG_ERROR, "BaseRngLib/x86: CPU BUG: RDRAND not reliable - disabling\n"));
     101    return FALSE;
     102  }
     103
     104  return TRUE;
     105}
     106
     107#undef ASM_RDRAND
    26108
    27109/**
     
    42124  )
    43125{
    44   UINT32  RegEcx;
     126  return EFI_SUCCESS;
     127}
     128
     129/**
     130  Generates a 16-bit random number.
     131
     132  @param[out] Rand     Buffer pointer to store the 16-bit random value.
     133
     134  @retval TRUE         Random number generated successfully.
     135  @retval FALSE        Failed to generate the random number.
     136
     137**/
     138BOOLEAN
     139EFIAPI
     140ArchGetRandomNumber16 (
     141  OUT     UINT16  *Rand
     142  )
     143{
     144  return AsmRdRand16 (Rand);
     145}
     146
     147/**
     148  Generates a 32-bit random number.
     149
     150  @param[out] Rand     Buffer pointer to store the 32-bit random value.
     151
     152  @retval TRUE         Random number generated successfully.
     153  @retval FALSE        Failed to generate the random number.
     154
     155**/
     156BOOLEAN
     157EFIAPI
     158ArchGetRandomNumber32 (
     159  OUT     UINT32  *Rand
     160  )
     161{
     162  return AsmRdRand32 (Rand);
     163}
     164
     165/**
     166  Generates a 64-bit random number.
     167
     168  @param[out] Rand     Buffer pointer to store the 64-bit random value.
     169
     170  @retval TRUE         Random number generated successfully.
     171  @retval FALSE        Failed to generate the random number.
     172
     173**/
     174BOOLEAN
     175EFIAPI
     176ArchGetRandomNumber64 (
     177  OUT     UINT64  *Rand
     178  )
     179{
     180  return AsmRdRand64 (Rand);
     181}
     182
     183/**
     184  Checks whether RDRAND is supported.
     185
     186  @retval TRUE         RDRAND is supported.
     187  @retval FALSE        RDRAND is not supported.
     188
     189**/
     190BOOLEAN
     191EFIAPI
     192ArchIsRngSupported (
     193  VOID
     194  )
     195{
     196  BOOLEAN  RdRandSupported;
     197  UINT32   RegEcx;
    45198
    46199  //
     
    49202  //
    50203  AsmCpuid (1, 0, 0, &RegEcx, 0);
    51   ASSERT ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
    52 
    53   mRdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
    54 
    55   return EFI_SUCCESS;
    56 }
    57 
    58 /**
    59   Generates a 16-bit random number.
    60 
    61   @param[out] Rand     Buffer pointer to store the 16-bit random value.
    62 
    63   @retval TRUE         Random number generated successfully.
    64   @retval FALSE        Failed to generate the random number.
    65 
    66 **/
    67 BOOLEAN
    68 EFIAPI
    69 ArchGetRandomNumber16 (
    70   OUT     UINT16  *Rand
    71   )
    72 {
    73   return AsmRdRand16 (Rand);
    74 }
    75 
    76 /**
    77   Generates a 32-bit random number.
    78 
    79   @param[out] Rand     Buffer pointer to store the 32-bit random value.
    80 
    81   @retval TRUE         Random number generated successfully.
    82   @retval FALSE        Failed to generate the random number.
    83 
    84 **/
    85 BOOLEAN
    86 EFIAPI
    87 ArchGetRandomNumber32 (
    88   OUT     UINT32  *Rand
    89   )
    90 {
    91   return AsmRdRand32 (Rand);
    92 }
    93 
    94 /**
    95   Generates a 64-bit random number.
    96 
    97   @param[out] Rand     Buffer pointer to store the 64-bit random value.
    98 
    99   @retval TRUE         Random number generated successfully.
    100   @retval FALSE        Failed to generate the random number.
    101 
    102 **/
    103 BOOLEAN
    104 EFIAPI
    105 ArchGetRandomNumber64 (
    106   OUT     UINT64  *Rand
    107   )
    108 {
    109   return AsmRdRand64 (Rand);
    110 }
    111 
    112 /**
    113   Checks whether RDRAND is supported.
    114 
    115   @retval TRUE         RDRAND is supported.
    116   @retval FALSE        RDRAND is not supported.
    117 
    118 **/
    119 BOOLEAN
    120 EFIAPI
    121 ArchIsRngSupported (
    122   VOID
    123   )
    124 {
    125   /*
    126      Existing software depends on this always returning TRUE, so for
    127      now hard-code it.
    128 
    129      return mRdRandSupported;
    130   */
    131   return TRUE;
     204
     205  RdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
     206
     207  if (RdRandSupported) {
     208    RdRandSupported = TestRdRand ();
     209  }
     210
     211  return RdRandSupported;
    132212}
    133213
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette