示例#1
0
/**
  Event handler registered with the Data Hub to parse EFI_DEBUG_CODE. This
  handler reads the Data Hub and sends any DEBUG info to StdErr.

  @param Event      The event that occured, not used
  @param Context    DataHub Protocol Pointer
**/
VOID
EFIAPI
DataHubStdErrEventHandler (
  IN EFI_EVENT Event,
  IN VOID      *Context
  )
{
  EFI_STATUS                           Status;
  EFI_DATA_HUB_PROTOCOL                *DataHub;
  EFI_DATA_RECORD_HEADER               *Record;
  DATA_HUB_STATUS_CODE_DATA_RECORD     *DataRecord;
  UINT64                               Mtc;
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL      *Sto;
  INT32                                OldAttribute;

  DataHub = (EFI_DATA_HUB_PROTOCOL *) Context;

  //
  // If StdErr is not yet initialized just return a DEBUG print in the BDS
  // after consoles are connect will make sure data gets flushed properly
  // when StdErr is available.
  //
  if (gST == NULL) {
    return ;
  }

  if (gST->StdErr == NULL) {
    return ;
  }

  //
  // Mtc of zero means return the next record that has not been read by the
  // event handler.
  //
  Mtc = 0;
  do {
    Status = DataHub->GetNextRecord (DataHub, &Mtc, &mDataHubStdErrEvent, &Record);
    if (!EFI_ERROR (Status)) {
      if (CompareGuid (&Record->DataRecordGuid, &gEfiDataHubStatusCodeRecordGuid)) {
        DataRecord = (DATA_HUB_STATUS_CODE_DATA_RECORD *) (((CHAR8 *) Record) + Record->HeaderSize);

        if (DataRecord->Data.HeaderSize > 0) {
          if (CompareGuid (&DataRecord->Data.Type, &gEfiStatusCodeDataTypeDebugGuid)) {
            //
            // If the Data record is from a DEBUG () then send it to Standard Error
            //
            Sto           = gST->StdErr;
            OldAttribute  = Sto->Mode->Attribute;
            Sto->SetAttribute (Sto, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));
            Sto->OutputString (Sto, (CHAR16 *) (DataRecord + 1));
            Sto->SetAttribute (Sto, OldAttribute);
          }
        }
      }
    }
  } while ((Mtc != 0) && !EFI_ERROR (Status));
}
示例#2
0
/**
  Entry Point of thunk driver.

  @param[in] ImageHandle  Image handle of this driver.
  @param[in] SystemTable  Pointer to EFI system table.

  @retval EFI_SUCCESS          The event handlers were registered.
  @retval EFI_DEVICE_ERROR     Failed to register the event handlers
**/
EFI_STATUS
EFIAPI
ThunkEntry (
    IN EFI_HANDLE         ImageHandle,
    IN EFI_SYSTEM_TABLE   *SystemTable
)
{
    EFI_STATUS            Status;
    EFI_DATA_HUB_PROTOCOL *DataHub;
    EFI_EVENT             FilterEvent;

    Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID**) &DataHub);
    ASSERT_EFI_ERROR (Status);
    ASSERT (DataHub != NULL);

    InitializeListHead (&mStructureList);

    //
    // Register SmBios Data Filter Function.
    // This function is notified at TPL_CALLBACK.
    //
    Status = gBS->CreateEvent (
                 EVT_NOTIFY_SIGNAL,
                 TPL_CALLBACK,
                 SmbiosDataFilter,
                 NULL,
                 &FilterEvent
             );
    if (EFI_ERROR (Status)) {
        return Status;
    }

    Status = DataHub->RegisterFilterDriver (
                 DataHub,
                 FilterEvent,
                 TPL_APPLICATION,
                 EFI_DATA_RECORD_CLASS_DATA,
                 NULL
             );
    if (EFI_ERROR (Status)) {
        gBS->CloseEvent (FilterEvent);
        return Status;
    }

    return Status;

}
示例#3
0
/**
  Smbios data filter function. This function is invoked when there is data records
  available in the Data Hub.

  @param Event         The event that is signaled.
  @param Context       not used here.
**/
VOID
EFIAPI
SmbiosDataFilter (
    IN EFI_EVENT    Event,
    IN VOID         *Context
)
{
    EFI_STATUS              Status;
    EFI_DATA_HUB_PROTOCOL   *DataHub;
    EFI_HANDLE              DataHubHandle;
    UINTN                   HandleSize;
    UINT64                  MonotonicCount;
    EFI_DATA_RECORD_HEADER  *Record;

    Status  = EFI_SUCCESS;
    DataHub = NULL;

    //
    // Get the Data Hub Protocol. Assume only one instance
    // of Data Hub Protocol is availabe in the system.
    //
    HandleSize = sizeof (EFI_HANDLE);

    Status = gBS->LocateHandle (
                 ByProtocol,
                 &gEfiDataHubProtocolGuid,
                 NULL,
                 &HandleSize,
                 &DataHubHandle
             );

    if (EFI_ERROR (Status)) {
        goto Done;
    }

    Status = gBS->HandleProtocol (
                 DataHubHandle,
                 &gEfiDataHubProtocolGuid,
                 (VOID **) &DataHub
             );

    if (EFI_ERROR (Status)) {
        goto Done;
    }
    //
    // Get all available data records from data hub
    //
    MonotonicCount  = 0;
    Record          = NULL;

    do {

        Status = DataHub->GetNextRecord (
                     DataHub,
                     &MonotonicCount,
                     &Event,
                     &Record
                 );

        if (!EFI_ERROR (Status)) {
            if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {

                //
                // It's of expected Data Type. Process it.
                //
                SmbiosProcessDataRecord (Record);
            }
        }
    } while (!EFI_ERROR (Status) && (MonotonicCount != 0));

Done:

    return ;

}
VOID
EFIAPI
WinNtIoProtocolNotifyFunction (
  IN EFI_EVENT                Event,
  IN VOID                     *Context
  )
/*++

Routine Description:
  This function will log memory size data to data hub.

Arguments:
Event        - Event whose notification function is being invoked.
Context      - Pointer to the notification function's context.

Returns:
    EFI_STATUS.

--*/
{
  EFI_STATUS                      Status;
  EFI_MEMORY_SUBCLASS_DRIVER_DATA MemorySubClassData;
  EFI_DATA_RECORD_HEADER          *Record;
  EFI_SUBCLASS_TYPE1_HEADER       *DataHeader;
  UINTN                           HandleCount;
  UINTN                           HandleIndex;
  UINT64                          MonotonicCount;
  BOOLEAN                         RecordFound;
  EFI_HANDLE                      *HandleBuffer;
  EFI_WIN_NT_IO_PROTOCOL          *WinNtIo;
  EFI_DATA_HUB_PROTOCOL           *DataHub;
  UINT64                          TotalMemorySize;

  DataHub         = NULL;
  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 DataHub protocol.
  //
  Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);
  if (EFI_ERROR (Status)) {
    return ;
  }
  //
  // Search the Handle array to find the meory size 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, &gEfiWinNtMemoryGuid)
          ) {
      //
      // 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 == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)
              ) {
            RecordFound = TRUE;
          }
        }
      } while (MonotonicCount != 0);

      if (RecordFound) {
        RecordFound = FALSE;
        continue;
      }
      //
      // Initialize data record.
      //
      MemorySubClassData.Header.Instance    = 1;
      MemorySubClassData.Header.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
      MemorySubClassData.Header.RecordType  = EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER;

      TotalMemorySize                       = (UINT64) Atoi (WinNtIo->EnvString);

      MemorySubClassData.Record.ArrayStartAddress.MemoryArrayStartAddress               = 0;
      MemorySubClassData.Record.ArrayStartAddress.MemoryArrayEndAddress                 = LShiftU64 (TotalMemorySize, 20) - 1;
      MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.ProducerName  = gMemoryProducerGuid;
      MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.Instance      = 1;
      MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
      MemorySubClassData.Record.ArrayStartAddress.MemoryArrayPartitionWidth = 0;

      //
      // Store memory size data record to data hub.
      //
      Status = DataHub->LogData (
                          DataHub,
                          &gEfiMemorySubClassGuid,
                          &gMemoryProducerGuid,
                          EFI_DATA_RECORD_CLASS_DATA,
                          &MemorySubClassData,
                          sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_ARRAY_START_ADDRESS)
                          );
    }

    gBS->CloseProtocol (
          HandleBuffer[HandleIndex],
          &gEfiWinNtIoProtocolGuid,
          Context,
          NULL
          );
  }
}
EFI_STATUS
EFIAPI
MiscSubclassDriverEntryPoint (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
/*++
Description:

  Standard EFI driver point.  This driver parses the mMiscSubclassDataTable
  structure and reports any generated data to the DataHub.

Arguments:

  ImageHandle
    Handle for the image of this driver

  SystemTable
    Pointer to the EFI System Table

Returns:

  EFI_SUCCESS
    The data was successfully reported to the Data Hub.

--*/
{
  EFI_MISC_SUBCLASS_DRIVER_DATA RecordData;
  EFI_DATA_HUB_PROTOCOL         *DataHub;
#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
  EFI_HII_DATABASE_PROTOCOL     *HiiDatabase;
  EFI_HII_PACKAGE_LIST_HEADER   *PackageList;
#else
  EFI_HII_PROTOCOL              *Hii;
  EFI_HII_PACKAGES              *PackageList;
#endif
  EFI_HII_HANDLE                HiiHandle;
  EFI_STATUS                    EfiStatus;
  UINTN                         Index;
  BOOLEAN                       LogRecordData;
  EFI_EVENT                     Event;
  VOID                          *Registration;

  //
  //
  //
  EfiInitializeDriverLib (ImageHandle, SystemTable);

  //
  // Initialize constant portion of subclass header.
  //
  RecordData.Header.Version     = EFI_MISC_SUBCLASS_VERSION;
  RecordData.Header.HeaderSize  = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
  RecordData.Header.Instance    = 1;
  RecordData.Header.SubInstance = 1;

  //
  // Locate data hub protocol.
  //
  EfiStatus = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);

  if (EFI_ERROR (EfiStatus)) {
    DEBUG ((EFI_D_ERROR, "Could not locate DataHub protocol.  %r\n", EfiStatus));
    return EfiStatus;
  } else if (DataHub == NULL) {
    DEBUG ((EFI_D_ERROR, "LocateProtocol(DataHub) returned NULL pointer!\n"));
    return EFI_DEVICE_ERROR;
  }
  //
  // Locate hii protocol.
  //
#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
  EfiStatus = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase);

  if (EFI_ERROR (EfiStatus)) {
    DEBUG ((EFI_D_ERROR, "Could not locate HiiDatabase protocol.  %r\n", EfiStatus));
    return EfiStatus;
  } else if (HiiDatabase == NULL) {
    DEBUG ((EFI_D_ERROR, "LocateProtocol(HiiDatabase) returned NULL pointer!\n"));
    return EFI_DEVICE_ERROR;
  }
  //
  // Add our default strings to the HII database. They will be modified later.
  //
  PackageList = PreparePackageList (1, &gEfiMiscSubClassGuid, MiscSubclassStrings);
  EfiStatus = HiiDatabase->NewPackageList (HiiDatabase, PackageList, ImageHandle, &HiiHandle);
#else
  EfiStatus = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii);

  if (EFI_ERROR (EfiStatus)) {
    DEBUG ((EFI_D_ERROR, "Could not locate Hii protocol.  %r\n", EfiStatus));
    return EfiStatus;
  } else if (Hii == NULL) {
    DEBUG ((EFI_D_ERROR, "LocateProtocol(Hii) returned NULL pointer!\n"));
    return EFI_DEVICE_ERROR;
  }
  //
  // Add our default strings to the HII database. They will be modified later.
  //
  PackageList = PreparePackages (1, &gEfiMiscSubClassGuid, MiscSubclassStrings);
  EfiStatus   = Hii->NewPack (Hii, PackageList, &HiiHandle);
#endif
  gBS->FreePool (PackageList);

  if (EFI_ERROR (EfiStatus)) {
    DEBUG ((EFI_D_ERROR, "Could not log default strings to Hii.  %r\n", EfiStatus));
    return EfiStatus;
  }
  //
  //
  //
  for (Index = 0; Index < mMiscSubclassDataTableEntries; ++Index) {
    //
    // Stupidity check!  Do nothing if RecordLen is zero.
    // %%TBD - Should this be an error or a mechanism for ignoring
    // records in the Data Table?
    //
    if (mMiscSubclassDataTable[Index].RecordLen == 0) {
      DEBUG (
        (EFI_D_ERROR,
        "mMiscSubclassDataTable[%d].RecordLen == 0\n",
        Index)
        );

      continue;
    }
    //
    // Initialize per-record portion of subclass header and
    // copy static data into data portion of subclass record.
    //
    RecordData.Header.RecordType = mMiscSubclassDataTable[Index].RecordType;

    if (mMiscSubclassDataTable[Index].RecordData == NULL) {
      EfiZeroMem (
        &RecordData.Record,
        mMiscSubclassDataTable[Index].RecordLen
        );
    } else {
      EfiCopyMem (
        &RecordData.Record,
        mMiscSubclassDataTable[Index].RecordData,
        mMiscSubclassDataTable[Index].RecordLen
        );
    }
    //
    // If the entry does not have a function pointer, just log the data.
    //
    if (mMiscSubclassDataTable[Index].Function == NULL) {
      //
      // Log RecordData to Data Hub.
      //
      EfiStatus = DataHub->LogData (
                            DataHub,
                            &gEfiMiscSubClassGuid,
                            &gEfiMiscSubClassGuid,
                            EFI_DATA_RECORD_CLASS_DATA,
                            &RecordData,
                            sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen
                            );

      if (EFI_ERROR (EfiStatus)) {
        DEBUG (
          (EFI_D_ERROR,
          "LogData(%d bytes) == %r\n",
          sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen,
          EfiStatus)
          );
      }

      continue;
    }
    //
    // The entry has a valid function pointer.
    // Keep calling the function and logging data until there
    // is no more data to log.
    //
    for (;;) {
      //
      //
      //
      EfiStatus = (*mMiscSubclassDataTable[Index].Function)
        (
          mMiscSubclassDataTable[Index].RecordType, &mMiscSubclassDataTable[Index].RecordLen, &RecordData.Record, &
            LogRecordData
        );

      //
      //
      //
      if (EFI_ERROR (EfiStatus)) {
        break;
      }

      if (!LogRecordData) {
        break;
      }
      //
      //
      //
      EfiStatus = DataHub->LogData (
                            DataHub,
                            &gEfiMiscSubClassGuid,
                            &gEfiMiscSubClassGuid,
                            EFI_DATA_RECORD_CLASS_DATA,
                            &RecordData,
                            sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen
                            );

      if (EFI_ERROR (EfiStatus)) {
        DEBUG (
          (EFI_D_ERROR,
          "LogData(%d bytes) == %r\n",
          sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen,
          EfiStatus)
          );
      }
    }
  }
  //
  // Install notify function to fetch memory data through WinNtIo protocol and store to data hub.
  //
  EfiStatus = gBS->CreateEvent (
                    EFI_EVENT_NOTIFY_SIGNAL,
                    EFI_TPL_CALLBACK,
                    WinNtIoProtocolNotifyFunction,
                    ImageHandle,
                    &Event
                    );
  ASSERT (!EFI_ERROR (EfiStatus));

  EfiStatus = gBS->RegisterProtocolNotify (
                    &gEfiWinNtIoProtocolGuid,
                    Event,
                    &Registration
                    );
  ASSERT (!EFI_ERROR (EfiStatus));

  return EFI_SUCCESS;
}