481 lines
11 KiB
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
|
|
|
|
|