alder_lake_bios/Lcfc/LfcPkg/Library/LfcUuidLib/UUID.c

481 lines
11 KiB
C

/*
* Lenovo Confidential
* Microcode Source Materials
* COPYRIGHT LENOVO 2005, 2012 All RIGHTS RESERVED
*/
#include <Library/UefiLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include "UUID.h"
#include "GETNODE.h"
static UINT32 rand_m;
static UINT32 rand_ia;
static UINT32 rand_ib;
static UINT32 rand_irand;
static UINT16 clock_seq;
static unsigned64_t time_last;
// *******************************************************************
//
// FUNCTION NAME.
// mult32
//
// FUNCTIONAL DESCRIPTION.
//
//
// ENTRY PARAMETERS.
//
// EXIT PARAMETERS.
//
// WARNINGS.
//
// *******************************************************************
static VOID
mult32(UINT32 u, UINT32 v, unsigned64_t *result)
{
/* Following the notation in Knuth, Vol. 2. */
UINT32 uuid1, uuid2, v1, v2, temp;
uuid1 = u >> 16;
uuid2 = u & 0xFFFF;
v1 = v >> 16;
v2 = v & 0xFFFF;
temp = uuid2 * v2;
result->lo = temp & 0xFFFF;
temp = uuid1 * v2 + (temp >> 16);
result->hi = temp >> 16;
temp = uuid2 * v1 + (temp & 0xFFFF);
result->lo += (temp & 0xFFFF) << 16;
result->hi += uuid1 * v1 + (temp >> 16);
} // mult32
// *******************************************************************
//
// FUNCTION NAME.
// new_clock_seq
//
// FUNCTIONAL DESCRIPTION.
//
//
// ENTRY PARAMETERS.
//
// EXIT PARAMETERS.
//
// WARNINGS.
//
// *******************************************************************
static VOID
new_clock_seq(VOID)
{
clock_seq = (clock_seq + 1) % (CLOCK_SEQ_LAST + 1);
if (clock_seq == 0) clock_seq = 1;
#ifdef NONVOLATILE_CLOCK
// write_clock(clock_seq);
#endif
} // new_clock_seq
// *******************************************************************
//
// FUNCTION NAME.
// time_cmp
//
// FUNCTIONAL DESCRIPTION.
//
//
// ENTRY PARAMETERS.
//
// EXIT PARAMETERS.
//
// WARNINGS.
//
// *******************************************************************
static int
time_cmp(
unsigned64_t *time1,
unsigned64_t *time2)
{
if (time1->hi < time2->hi) return -1;
if (time1->hi > time2->hi) return 1;
if (time1->lo < time2->lo) return -1;
if (time1->lo > time2->lo) return 1;
return 0;
} // time_cmp
// *******************************************************************
//
// FUNCTION NAME.
// true_random
//
// FUNCTIONAL DESCRIPTION.
//
//
// ENTRY PARAMETERS.
//
// EXIT PARAMETERS.
//
// WARNINGS.
//
// *******************************************************************
static UINT16
true_random(VOID)
{
if ((rand_m += 7) >= 9973)
rand_m -= 9871;
if ((rand_ia += 1907) >= 99991)
rand_ia -= 89989;
if ((rand_ib += 73939) >= 224729)
rand_ib -= 96233;
rand_irand = (rand_irand * rand_m) + rand_ia + rand_ib;
return (UINT16)( (rand_irand >> 16) ^ (rand_irand & RAND_MASK) );
} // true_random
// *******************************************************************
//
// FUNCTION NAME.
// get_system_time
//
// FUNCTIONAL DESCRIPTION.
//
// ENTRY PARAMETERS.
//
// EXIT PARAMETERS.
//
// WARNINGS.
//
// *******************************************************************
static EFI_STATUS
get_system_time(unsigned64_t *uuid_time)
{
EFI_STATUS Status;
EFI_TIME Time;
#ifdef HOZU
// struct timeval tp;
#endif
unsigned64_t utc = {0UL, 0UL};
unsigned64_t usecs = {0UL, 0UL};
unsigned64_t os_basetime_diff = {0UL, 0UL};
#ifdef HOZU
// gettimeofday(&tp, (struct timezone *)0); //
// mult32((long)tp.tv_sec, 10000000, &utc); // timeval.tv_sec : second
// mult32((long)tp.tv_usec, 10, &usecs); // timeval.tv_usec : microsecond
#else
{
unsigned short theDays;
unsigned char h, m, s;
unsigned long theSec;
unsigned long theUSec; // original is u_char
theDays = 0;
h = m = s = 0;
theSec = 0;
theUSec = 0;
ZeroMem (&Time, sizeof (EFI_TIME));
// Get System Time
Status = gRT->GetTime (&Time, NULL);
if (EFI_ERROR (Status)) {
DEBUG((EFI_D_ERROR, "ERROR : Get Time, Status=[%r]\n", Status));
return Status;
}
theSec = ( unsigned long )Time.Day * 86400L +
( unsigned long )Time.Hour * 3600L +
( unsigned long )Time.Minute * 60L +
( unsigned long )Time.Second;
if(Time.Nanosecond != 0){
theUSec = Time.Nanosecond;
}else{
theUSec = true_random(); // substitute for Nanosecond
}
//--------------------------------------------------------------------
// __asm
// {
// mov ah, 4
// int 0x1a
// mov theDays, cx
// mov ah,2
// int 0x1a
// mov h, ch
// mov m, cl
// mov s, dh
// }
//
// theSec = ( unsigned long )theDays * 86400L +
// ( unsigned long )h * 3600L +
// ( unsigned long )m * 60L +
// ( unsigned long )s;
//
// __asm
// {
// mov ah, 0
// int 0x1a
// mov theUSec, al // theUSec : unsigned char
// }
//--------------------------------------------------------------------
mult32((long)theSec, 10000000, &utc);
mult32((long)theUSec, 10, &usecs);
}
#endif
ADD_64b_2_64b(&usecs, &utc, &utc);
/* Offset between UUID formatted times and Unix formatted times.
* UUID UTC base time is October 15, 1582.
* Unix base time is January 1, 1970. */
os_basetime_diff.lo = 0x13814000;
os_basetime_diff.hi = 0x01B21DD2;
ADD_64b_2_64b(&utc, &os_basetime_diff, uuid_time);
return EFI_SUCCESS;
} // get_system_time
// *******************************************************************
//
// FUNCTION NAME.
// true_random_init
//
// FUNCTIONAL DESCRIPTION.
//
// ENTRY PARAMETERS.
//
// EXIT PARAMETERS.
//
// WARNINGS.
//
// *******************************************************************
static EFI_STATUS
true_random_init(VOID)
{
EFI_STATUS Status;
unsigned64_t t;
UINT16 seed;
Status = EFI_SUCCESS;
seed = 0;
ZeroMem (&t, sizeof(t));
/* Generating our 'seed' value Start with the current time, but,
* since the resolution of clocks is system hardware dependent and
* most likely coarser than our resolution (10 usec) we 'mixup' the
* bits by xor'ing all the bits together. This will have the effect
* of involving all of the bits in the determination of the seed
* value while remaining system independent. Then for good measure
* to ensure a unique seed when there are multiple processes
* creating UUIDs on a system, we add in the PID.
*/
rand_m = 971;
rand_ia = 11113;
rand_ib = 104322;
rand_irand = 4181;
Status = get_system_time(&t);
if (EFI_ERROR (Status)) {
return Status;
}
seed = (UINT16)t.lo & 0xFFFF;
seed = (UINT16)(t.lo >> 16) & 0xFFFF;
seed = (UINT16) t.hi & 0xFFFF;
seed = (UINT16)(t.hi >> 16) & 0xFFFF;
#ifdef HOZU
// rand_irand += seed + getpid();
#else
rand_irand += seed;
#endif
return EFI_SUCCESS;
} // true_random_init
// *******************************************************************
//
// FUNCTION NAME.
// uuid_init
//
// FUNCTIONAL DESCRIPTION.
//
// ENTRY PARAMETERS.
//
// EXIT PARAMETERS.
//
// WARNINGS.
//
// *******************************************************************
EFI_STATUS
uuid_init(
VOID)
{
EFI_STATUS Status;
// Initialize
Status = EFI_SUCCESS;
// Make seed from system time
Status = true_random_init();
if (EFI_ERROR (Status)) {
DEBUG((EFI_D_ERROR, "ERROR : true random init, Status=[%r]\n", Status));
return Status;
}
// Get system time after calculation
Status = get_system_time(&time_last);
if (EFI_ERROR (Status)) {
DEBUG((EFI_D_ERROR, "ERROR : get system time, Status=[%r]\n", Status));
return Status;
}
#ifdef NONVOLATILE_CLOCK
// clock_seq = read_clock();
#else
// Make "clock_seq"
clock_seq = true_random();
#endif
return EFI_SUCCESS;
} // uuid_init
// *******************************************************************
//
// FUNCTION NAME.
// uuid_create
//
// FUNCTIONAL DESCRIPTION.
//
//
// ENTRY PARAMETERS.
//
// EXIT PARAMETERS.
//
// WARNINGS.
//
// *******************************************************************
EFI_STATUS
uuid_create(uuid_t *uuid)
{
EFI_STATUS Status;
static unsigned64_t time_now;
static UINT16 time_adjust;
UINT8 eaddr[6];
UINTN got_no_time = 0;
UINTN i;
UINTN tempSize;
unsigned char theBuff[8 + sizeof(UINT16)];
// Initialize
Status = EFI_SUCCESS;
ZeroMem (eaddr, sizeof(eaddr));
ZeroMem (theBuff, sizeof(theBuff));
//
// UUID create
//
#ifdef HOZU
// get_ieee_node_identifier(&eaddr); /* TO BE PROVIDED */
#else
{
//#if defined(_M_AMD64)
*(UINT64*)(theBuff) = AsmReadTsc();
//#else
// // -----------------------------------------------------------
// // Get total CPU clock count from the started (8byte)
// // eax : low byte (4byte), edx : high byte (4byte)
// // -----------------------------------------------------------
// __asm
// {
// rdtsc
// mov dword ptr theBuff[0], eax
// mov dword ptr theBuff[4], edx
// }
// // -----------------------------------------------------------
//#endif
*( UINT16 * )&theBuff[8] = true_random();
GenNodeID( ( unsigned char * )theBuff, sizeof( theBuff ), eaddr );
}
#endif
do {
Status = get_system_time(&time_now);
switch (time_cmp(&time_now, &time_last)) {
case -1:
/* Time went backwards. */
new_clock_seq();
time_adjust = 0;
break;
case 1:
time_adjust = 0;
break;
default:
if (time_adjust == 0x7FFF)
/* We're going too fast for our clock; spin. */
got_no_time = 1;
else
time_adjust++;
break;
}
} while (got_no_time);
time_last.lo = time_now.lo;
time_last.hi = time_now.hi;
if (time_adjust != 0) {
ADD_16b_2_64b(&time_adjust, &time_now, &time_now);
}
/* Construct a uuid with the information we've gathered
* plus a few constants. */
uuid->time_low = time_now.lo;
uuid->time_mid = (UINT16)( time_now.hi & 0x0000FFFF );
uuid->time_hi_and_version = (UINT16)((time_now.hi & 0x0FFF0000) >> 16);
uuid->time_hi_and_version |= (1 << 12);
uuid->clock_seq_low = (UINT8)( clock_seq & 0xFF );
uuid->clock_seq_hi_and_reserved = (UINT8)((clock_seq & 0x3F00) >> 8);
uuid->clock_seq_hi_and_reserved |= 0x80;
//memcpy(uuid->node, &eaddr, sizeof uuid->node);
tempSize = sizeof(uuid->node);
for(i=0 ; i<tempSize ; i++){
uuid->node[i] = eaddr[i];
}
return EFI_SUCCESS;
} // uuid_create