cpu.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 745 行 · 第 1/2 页

C
745
字号

  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 EFI Spec conformance
  //
  if (Length == 0) {
    return EFI_INVALID_PARAMETER;
  }

  if ((BaseAddress &~EFI_CACHE_VALID_ADDRESS) != 0 || (Length &~EFI_CACHE_VALID_ADDRESS) != 0) {
    return EFI_UNSUPPORTED;
  }
  //
  // Do nothing for Nt32 emulation
  //
  Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This);
  return EFI_UNSUPPORTED;
}

EFI_DRIVER_ENTRY_POINT (InitializeCpu)

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;

  EfiInitializeDriverLib (ImageHandle, SystemTable);

  EfiInitializeWinNtDriverLib (ImageHandle, SystemTable);

  Status = gBS->AllocatePool (
                  EfiBootServicesData,
                  sizeof (CPU_ARCH_PROTOCOL_PRIVATE),
                  &Private
                  );
  ASSERT_EFI_ERROR (Status);

  Private->Signature                    = CPU_ARCH_PROT_PRIVATE_SIGNATURE;
  Private->Cpu.FlushDataCache           = WinNtFlushCpuDataCache;
  Private->Cpu.EnableInterrupt          = WinNtEnableInterrupt;
  Private->Cpu.DisableInterrupt         = WinNtDisableInterrupt;
  Private->Cpu.GetInterruptState        = WinNtGetInterruptState;
  Private->Cpu.Init                     = WinNtInit;
  Private->Cpu.RegisterInterruptHandler = WinNtRegisterInterruptHandler;
  Private->Cpu.GetTimerValue            = WinNtGetTimerValue;
  Private->Cpu.SetMemoryAttributes      = WinNtSetMemoryAttributes;

  Private->Cpu.NumberOfTimers           = 0;
  Private->Cpu.DmaBufferAlignment       = 4;

  Private->InterruptState               = TRUE;

  Private->Handle                       = NULL;
  Status = gBS->InstallProtocolInterface (
                  &Private->Handle,
                  &gEfiCpuArchProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  &Private->Cpu
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Install notify function to store processor data to HII database and data hub.
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL,
                  EFI_TPL_CALLBACK,
                  WinNtIoProtocolNotifyFunction,
                  ImageHandle,
                  &Event
                  );
  ASSERT (!EFI_ERROR (Status));

  Status = gBS->RegisterProtocolNotify (
                  &gEfiWinNtIoProtocolGuid,
                  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 (
  CHAR16  *String
  )
/*++

Routine Description:
  Convert a unicode string to a UINTN

Arguments:
  String - Unicode string.

Returns: 
  UINTN of the number represented by String.  

--*/
{
  UINTN   Number;
  CHAR16  *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
WinNtIoProtocolNotifyFunction (
  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_WIN_NT_IO_PROTOCOL      *WinNtIo;
  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,
                  &gEfiWinNtIoProtocolGuid,
                  NULL,
                  &HandleCount,
                  &HandleBuffer
                  );
  if (EFI_ERROR (Status)) {
    return ;
  }
  //
  // Locate HII protocol
  //
  Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii);
  if (EFI_ERROR (Status)) {
    return ;
  }
  //
  // Locate DataHub protocol.
  //
  Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);
  if (EFI_ERROR (Status)) {
    return ;
  }
  //
  // Initialize data record header
  //
  mCpuDataRecordHeader.Instance = 1;
  HeaderSize                    = sizeof (EFI_SUBCLASS_TYPE1_HEADER);

  RecordBuffer.Raw              = EfiLibAllocatePool (HeaderSize + EFI_CPU_DATA_MAXIMUM_LENGTH);
  if (RecordBuffer.Raw == NULL) {
    return ;
  }

  EfiCopyMem (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],
                    &gEfiWinNtIoProtocolGuid,
                    &WinNtIo,
                    Context,
                    NULL,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (EFI_ERROR (Status)) {
      continue;
    }

    if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) &&
        EfiCompareGuid (WinNtIo->TypeGuid, &gEfiWinNtCPUModelGuid)
          ) {
      //
      // 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 (EfiCompareGuid (&Record->DataRecordGuid, &gProcessorSubClassName) &&
              (DataHeader->RecordType == ProcessorVersionRecordType)
              ) {
            RecordFound = TRUE;
          }
        }
      } while (MonotonicCount != 0);

      if (RecordFound) {
        RecordFound = FALSE;
        continue;
      }
      //
      // Initialize strings to HII database
      //
      PackageList = PreparePackages (1, &gProcessorProducerGuid, STRING_ARRAY_NAME);

      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, WinNtIo->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,
                          &gProcessorSubClassName,
                          &gProcessorProducerGuid,
                          EFI_DATA_RECORD_CLASS_DATA,
                          RecordBuffer.Raw,
                          TotalSize
                          );
    }

    if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) &&
        EfiCompareGuid (WinNtIo->TypeGuid, &gEfiWinNtCPUSpeedGuid)
          ) {
      //
      // 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 (EfiCompareGuid (&Record->DataRecordGuid, &gProcessorSubClassName) &&
              (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 (WinNtIo->EnvString);
      RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Exponent = 6;
      TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_FREQUENCY_DATA);

      Status = DataHub->LogData (
                          DataHub,
                          &gProcessorSubClassName,
                          &gProcessorProducerGuid,
                          EFI_DATA_RECORD_CLASS_DATA,
                          RecordBuffer.Raw,
                          TotalSize
                          );

      gBS->FreePool (RecordBuffer.Raw);
    }

    gBS->CloseProtocol (
          HandleBuffer[HandleIndex],
          &gEfiWinNtIoProtocolGuid,
          Context,
          NULL
          );
  }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?