Changed old event definitions reference to these new event definitions. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2729 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			731 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			731 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006, Intel Corporation
 | 
						|
All rights reserved. This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  Cpu.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  Unix Emulation Architectural Protocol Driver as defined in Tiano.
 | 
						|
  This CPU module abstracts the interrupt subsystem of a platform and
 | 
						|
  the CPU-specific setjump/long pair.  Other services are not implemented
 | 
						|
  in this driver.
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include "CpuDriver.h"
 | 
						|
 | 
						|
#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
InitializeCpu (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  );
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
UnixIoProtocolNotifyFunction (
 | 
						|
  IN EFI_EVENT                Event,
 | 
						|
  IN VOID                     *Context
 | 
						|
  );
 | 
						|
 | 
						|
typedef union {
 | 
						|
  EFI_CPU_DATA_RECORD *DataRecord;
 | 
						|
  UINT8               *Raw;
 | 
						|
} EFI_CPU_DATA_RECORD_BUFFER;
 | 
						|
 | 
						|
EFI_SUBCLASS_TYPE1_HEADER mCpuDataRecordHeader = {
 | 
						|
  EFI_PROCESSOR_SUBCLASS_VERSION,       // Version
 | 
						|
  sizeof (EFI_SUBCLASS_TYPE1_HEADER),   // Header Size
 | 
						|
  0,                                    // Instance, Initialize later
 | 
						|
  EFI_SUBCLASS_INSTANCE_NON_APPLICABLE, // SubInstance
 | 
						|
  0                                     // RecordType, Initialize later
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// Service routines for the driver
 | 
						|
//
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixFlushCpuDataCache (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS   Start,
 | 
						|
  IN UINT64                 Length,
 | 
						|
  IN EFI_CPU_FLUSH_TYPE     FlushType
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would provide support for flushing the CPU data cache.
 | 
						|
  In the case of UNIX emulation environment, this flushing is not necessary and
 | 
						|
  is thus not implemented.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
  Start adddress in memory to flush
 | 
						|
  Length of memory to flush
 | 
						|
  Flush type
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_SUCCESS
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    FlushType - add argument and description to function comment
 | 
						|
// TODO:    EFI_UNSUPPORTED - add return value to function comment
 | 
						|
{
 | 
						|
  if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
 | 
						|
    //
 | 
						|
    // Only WB flush is supported. We actually need do nothing on UNIX emulator
 | 
						|
    // environment. Classify this to follow EFI spec
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Other flush types are not supported by UNIX emulator
 | 
						|
  //
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixEnableInterrupt (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine provides support for emulation of the interrupt enable of the
 | 
						|
  the system.  For our purposes, CPU enable is just a BOOLEAN that the Timer
 | 
						|
  Architectural Protocol observes in order to defer behaviour while in its
 | 
						|
  emulated interrupt, or timer tick.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_SUCCESS
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  Private                 = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  Private->InterruptState = TRUE;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixDisableInterrupt (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine provides support for emulation of the interrupt disable of the
 | 
						|
  the system.  For our purposes, CPU enable is just a BOOLEAN that the Timer
 | 
						|
  Architectural Protocol observes in order to defer behaviour while in its
 | 
						|
  emulated interrupt, or timer tick.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_SUCCESS
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  Private                 = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  Private->InterruptState = FALSE;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixGetInterruptState (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This,
 | 
						|
  OUT BOOLEAN               *State
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine provides support for emulation of the interrupt disable of the
 | 
						|
  the system.  For our purposes, CPU enable is just a BOOLEAN that the Timer
 | 
						|
  Architectural Protocol observes in order to defer behaviour while in its
 | 
						|
  emulated interrupt, or timer tick.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_SUCCESS
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    State - add argument and description to function comment
 | 
						|
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  if (State == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  *State  = Private->InterruptState;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixInit (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This,
 | 
						|
  IN EFI_CPU_INIT_TYPE      InitType
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would support generation of a CPU INIT.  At
 | 
						|
  present, this code does not provide emulation.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
  INIT Type
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_UNSUPPORTED - not yet implemented
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    InitType - add argument and description to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixRegisterInterruptHandler (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL      *This,
 | 
						|
  IN EFI_EXCEPTION_TYPE         InterruptType,
 | 
						|
  IN EFI_CPU_INTERRUPT_HANDLER  InterruptHandler
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would support registration of an interrupt handler.  At
 | 
						|
  present, this code does not provide emulation.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
  Pointer to interrupt handlers
 | 
						|
  Interrupt type
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_UNSUPPORTED - not yet implemented
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    InterruptType - add argument and description to function comment
 | 
						|
// TODO:    InterruptHandler - add argument and description to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  //
 | 
						|
  // Do parameter checking for EFI spec conformance
 | 
						|
  //
 | 
						|
  if (InterruptType < 0 || InterruptType > 0xff) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Do nothing for Nt32 emulation
 | 
						|
  //
 | 
						|
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixGetTimerValue (
 | 
						|
  IN  EFI_CPU_ARCH_PROTOCOL *This,
 | 
						|
  IN  UINT32                TimerIndex,
 | 
						|
  OUT UINT64                *TimerValue,
 | 
						|
  OUT UINT64                *TimerPeriod OPTIONAL
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would support querying of an on-CPU timer.  At present,
 | 
						|
  this code does not provide timer emulation.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  This        - Pointer to CPU Architectural Protocol interface
 | 
						|
  TimerIndex  - Index of given CPU timer
 | 
						|
  TimerValue  - Output of the timer
 | 
						|
  TimerPeriod - Output of the timer period
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_UNSUPPORTED       - not yet implemented
 | 
						|
  EFI_INVALID_PARAMETER - TimeValue is NULL
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  if (TimerValue == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // No timer supported
 | 
						|
  //
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixSetMemoryAttributes (
 | 
						|
  IN EFI_CPU_ARCH_PROTOCOL  *This,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS   BaseAddress,
 | 
						|
  IN UINT64                 Length,
 | 
						|
  IN UINT64                 Attributes
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This routine would support querying of an on-CPU timer.  At present,
 | 
						|
  this code does not provide timer emulation.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Pointer to CPU Architectural Protocol interface
 | 
						|
  Start address of memory region
 | 
						|
  The size in bytes of the memory region
 | 
						|
  The bit mask of attributes to set for the memory region
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
    EFI_UNSUPPORTED - not yet implemented
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    This - add argument and description to function comment
 | 
						|
// TODO:    BaseAddress - add argument and description to function comment
 | 
						|
// TODO:    Length - add argument and description to function comment
 | 
						|
// TODO:    Attributes - add argument and description to function comment
 | 
						|
// TODO:    EFI_INVALID_PARAMETER - add return value to function comment
 | 
						|
{
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid parameter for Spec conformance
 | 
						|
  //
 | 
						|
  if (Length == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do nothing for Nt32 emulation
 | 
						|
  //
 | 
						|
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
InitializeCpu (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Initialize the state information for the CPU Architectural Protocol
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  ImageHandle of the loaded driver
 | 
						|
  Pointer to the System Table
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status
 | 
						|
 | 
						|
  EFI_SUCCESS           - protocol instance can be published
 | 
						|
  EFI_OUT_OF_RESOURCES  - cannot allocate protocol data structure
 | 
						|
  EFI_DEVICE_ERROR      - cannot create the thread
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    SystemTable - add argument and description to function comment
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_EVENT                 Event;
 | 
						|
  CPU_ARCH_PROTOCOL_PRIVATE *Private;
 | 
						|
  VOID                      *Registration;
 | 
						|
 | 
						|
  Status = gBS->AllocatePool (
 | 
						|
                  EfiBootServicesData,
 | 
						|
                  sizeof (CPU_ARCH_PROTOCOL_PRIVATE),
 | 
						|
                  (VOID **)&Private
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Private->Signature                    = CPU_ARCH_PROT_PRIVATE_SIGNATURE;
 | 
						|
  Private->Cpu.FlushDataCache           = UnixFlushCpuDataCache;
 | 
						|
  Private->Cpu.EnableInterrupt          = UnixEnableInterrupt;
 | 
						|
  Private->Cpu.DisableInterrupt         = UnixDisableInterrupt;
 | 
						|
  Private->Cpu.GetInterruptState        = UnixGetInterruptState;
 | 
						|
  Private->Cpu.Init                     = UnixInit;
 | 
						|
  Private->Cpu.RegisterInterruptHandler = UnixRegisterInterruptHandler;
 | 
						|
  Private->Cpu.GetTimerValue            = UnixGetTimerValue;
 | 
						|
  Private->Cpu.SetMemoryAttributes      = UnixSetMemoryAttributes;
 | 
						|
 | 
						|
  Private->Cpu.NumberOfTimers           = 0;
 | 
						|
  Private->Cpu.DmaBufferAlignment       = 4;
 | 
						|
 | 
						|
  Private->InterruptState               = TRUE;
 | 
						|
 | 
						|
  Private->CpuIo.Mem.Read   = CpuMemoryServiceRead;
 | 
						|
  Private->CpuIo.Mem.Write  = CpuMemoryServiceWrite;
 | 
						|
  Private->CpuIo.Io.Read    = CpuIoServiceRead;
 | 
						|
  Private->CpuIo.Io.Write   = CpuIoServiceWrite;
 | 
						|
 | 
						|
 | 
						|
  Private->Handle                       = NULL;
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &Private->Handle,
 | 
						|
                  &gEfiCpuArchProtocolGuid,   &Private->Cpu,
 | 
						|
                  &gEfiCpuIoProtocolGuid,     &Private->CpuIo,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Install notify function to store processor data to HII database and data hub.
 | 
						|
  //
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  UnixIoProtocolNotifyFunction,
 | 
						|
                  ImageHandle,
 | 
						|
                  &Event
 | 
						|
                  );
 | 
						|
  ASSERT (!EFI_ERROR (Status));
 | 
						|
 | 
						|
  Status = gBS->RegisterProtocolNotify (
 | 
						|
                  &gEfiUnixIoProtocolGuid,
 | 
						|
                  Event,
 | 
						|
                  &Registration
 | 
						|
                  );
 | 
						|
  ASSERT (!EFI_ERROR (Status));
 | 
						|
 | 
						|
  //
 | 
						|
  // Should be at EFI_D_INFO, but lets us now things are running
 | 
						|
  //
 | 
						|
  DEBUG ((EFI_D_ERROR, "CPU Architectural Protocol Loaded\n"));
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
UINTN
 | 
						|
Atoi (
 | 
						|
  UINT16  *String
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Convert a unicode string to a UINTN
 | 
						|
 | 
						|
Arguments:
 | 
						|
  String - Unicode string.
 | 
						|
 | 
						|
Returns:
 | 
						|
  UINTN of the number represented by String.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN   Number;
 | 
						|
  UINT16   *Str;
 | 
						|
 | 
						|
  //
 | 
						|
  // skip preceeding white space
 | 
						|
  //
 | 
						|
  Str = String;
 | 
						|
  while ((*Str) && (*Str == ' ' || *Str == '"')) {
 | 
						|
    Str++;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Convert ot a Number
 | 
						|
  //
 | 
						|
  Number = 0;
 | 
						|
  while (*Str != '\0') {
 | 
						|
    if ((*Str >= '0') && (*Str <= '9')) {
 | 
						|
      Number = (Number * 10) +*Str - '0';
 | 
						|
    } else {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Str++;
 | 
						|
  }
 | 
						|
 | 
						|
  return Number;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
UnixIoProtocolNotifyFunction (
 | 
						|
  IN EFI_EVENT                Event,
 | 
						|
  IN VOID                     *Context
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  This function will log processor version and frequency data to data hub.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Event        - Event whose notification function is being invoked.
 | 
						|
  Context      - Pointer to the notification function's context.
 | 
						|
 | 
						|
Returns:
 | 
						|
  None.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  EFI_CPU_DATA_RECORD_BUFFER  RecordBuffer;
 | 
						|
  EFI_DATA_RECORD_HEADER      *Record;
 | 
						|
  EFI_SUBCLASS_TYPE1_HEADER   *DataHeader;
 | 
						|
  UINT32                      HeaderSize;
 | 
						|
  UINT32                      TotalSize;
 | 
						|
  UINTN                       HandleCount;
 | 
						|
  UINTN                       HandleIndex;
 | 
						|
  UINT64                      MonotonicCount;
 | 
						|
  BOOLEAN                     RecordFound;
 | 
						|
  EFI_HANDLE                  *HandleBuffer;
 | 
						|
  EFI_UNIX_IO_PROTOCOL       *UnixIo;
 | 
						|
  EFI_DATA_HUB_PROTOCOL       *DataHub;
 | 
						|
  EFI_HII_PROTOCOL            *Hii;
 | 
						|
  EFI_HII_HANDLE              StringHandle;
 | 
						|
  EFI_HII_PACKAGES            *PackageList;
 | 
						|
  STRING_REF                  Token;
 | 
						|
 | 
						|
  DataHub         = NULL;
 | 
						|
  Token           = 0;
 | 
						|
  MonotonicCount  = 0;
 | 
						|
  RecordFound     = FALSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve the list of all handles from the handle database
 | 
						|
  //
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  AllHandles,
 | 
						|
                  &gEfiUnixIoProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &HandleCount,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Locate HII protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **)&Hii);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Locate DataHub protocol.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **)&DataHub);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Initialize data record header
 | 
						|
  //
 | 
						|
  mCpuDataRecordHeader.Instance = 1;
 | 
						|
  HeaderSize                    = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
 | 
						|
 | 
						|
  RecordBuffer.Raw              = AllocatePool (HeaderSize + EFI_CPU_DATA_MAXIMUM_LENGTH);
 | 
						|
  if (RecordBuffer.Raw == NULL) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (RecordBuffer.Raw, &mCpuDataRecordHeader, HeaderSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Search the Handle array to find the CPU model and speed information
 | 
						|
  //
 | 
						|
  for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    HandleBuffer[HandleIndex],
 | 
						|
                    &gEfiUnixIoProtocolGuid,
 | 
						|
                    (VOID **)&UnixIo,
 | 
						|
                    Context,
 | 
						|
                    NULL,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((UnixIo->UnixThunk->Signature == EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) &&
 | 
						|
        CompareGuid (UnixIo->TypeGuid, &gEfiUnixCPUModelGuid)
 | 
						|
          ) {
 | 
						|
      //
 | 
						|
      // Check if this record has been stored in data hub
 | 
						|
      //
 | 
						|
      do {
 | 
						|
        Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);
 | 
						|
        if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {
 | 
						|
          DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);
 | 
						|
          if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&
 | 
						|
              (DataHeader->RecordType == ProcessorVersionRecordType)
 | 
						|
              ) {
 | 
						|
            RecordFound = TRUE;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } while (MonotonicCount != 0);
 | 
						|
 | 
						|
      if (RecordFound) {
 | 
						|
        RecordFound = FALSE;
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Initialize strings to HII database
 | 
						|
      //
 | 
						|
      PackageList = PreparePackages (1, &gEfiProcessorProducerGuid, CpuStrings);
 | 
						|
 | 
						|
      Status      = Hii->NewPack (Hii, PackageList, &StringHandle);
 | 
						|
      ASSERT (!EFI_ERROR (Status));
 | 
						|
 | 
						|
      gBS->FreePool (PackageList);
 | 
						|
 | 
						|
      //
 | 
						|
      // Store processor version data record to data hub
 | 
						|
      //
 | 
						|
      Status = Hii->NewString (Hii, NULL, StringHandle, &Token, UnixIo->EnvString);
 | 
						|
      ASSERT (!EFI_ERROR (Status));
 | 
						|
 | 
						|
      RecordBuffer.DataRecord->DataRecordHeader.RecordType      = ProcessorVersionRecordType;
 | 
						|
      RecordBuffer.DataRecord->VariableRecord.ProcessorVersion  = Token;
 | 
						|
      TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_VERSION_DATA);
 | 
						|
 | 
						|
      Status = DataHub->LogData (
 | 
						|
                          DataHub,
 | 
						|
                          &gEfiProcessorSubClassGuid,
 | 
						|
                          &gEfiProcessorProducerGuid,
 | 
						|
                          EFI_DATA_RECORD_CLASS_DATA,
 | 
						|
                          RecordBuffer.Raw,
 | 
						|
                          TotalSize
 | 
						|
                          );
 | 
						|
    }
 | 
						|
 | 
						|
    if ((UnixIo->UnixThunk->Signature == EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) &&
 | 
						|
        CompareGuid (UnixIo->TypeGuid, &gEfiUnixCPUSpeedGuid)
 | 
						|
          ) {
 | 
						|
      //
 | 
						|
      // Check if this record has been stored in data hub
 | 
						|
      //
 | 
						|
      do {
 | 
						|
        Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);
 | 
						|
        if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {
 | 
						|
          DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);
 | 
						|
          if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&
 | 
						|
              (DataHeader->RecordType == ProcessorCoreFrequencyRecordType)
 | 
						|
              ) {
 | 
						|
            RecordFound = TRUE;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } while (MonotonicCount != 0);
 | 
						|
 | 
						|
      if (RecordFound) {
 | 
						|
        RecordFound = FALSE;
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Store CPU frequency data record to data hub
 | 
						|
      //
 | 
						|
      RecordBuffer.DataRecord->DataRecordHeader.RecordType                    = ProcessorCoreFrequencyRecordType;
 | 
						|
      RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Value    = (UINT16) Atoi (UnixIo->EnvString);
 | 
						|
      RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Exponent = 6;
 | 
						|
      TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_FREQUENCY_DATA);
 | 
						|
 | 
						|
      Status = DataHub->LogData (
 | 
						|
                          DataHub,
 | 
						|
                          &gEfiProcessorSubClassGuid,
 | 
						|
                          &gEfiProcessorProducerGuid,
 | 
						|
                          EFI_DATA_RECORD_CLASS_DATA,
 | 
						|
                          RecordBuffer.Raw,
 | 
						|
                          TotalSize
 | 
						|
                          );
 | 
						|
 | 
						|
      gBS->FreePool (RecordBuffer.Raw);
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          HandleBuffer[HandleIndex],
 | 
						|
          &gEfiUnixIoProtocolGuid,
 | 
						|
          Context,
 | 
						|
          NULL
 | 
						|
          );
 | 
						|
  }
 | 
						|
}
 |