/** Dump SMI handler in HandlerCategory. @param HandlerCategory SMI handler category **/ VOID DumpSmiHandler( IN UINT32 HandlerCategory ) { SMM_CORE_SMI_DATABASE_STRUCTURE *SmiStruct; SMM_CORE_SMI_HANDLER_STRUCTURE *SmiHandlerStruct; UINTN Index; SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct; CHAR8 *NameString; SmiStruct = (VOID *)mSmiHandlerProfileDatabase; while ((UINTN)SmiStruct < (UINTN)mSmiHandlerProfileDatabase + mSmiHandlerProfileDatabaseSize) { if ((SmiStruct->Header.Signature == SMM_CORE_SMI_DATABASE_SIGNATURE) && (SmiStruct->HandlerCategory == HandlerCategory)) { SmiHandlerStruct = (VOID *)(SmiStruct + 1); Print(L" <SmiEntry"); if (!IsZeroGuid (&SmiStruct->HandlerType)) { Print(L" HandlerType=\"%g\"", &SmiStruct->HandlerType); } Print(L">\n"); for (Index = 0; Index < SmiStruct->HandlerCount; Index++) { Print(L" <SmiHandler"); if (SmiHandlerStruct->ContextBufferSize != 0) { DumpSmiChildContext (&SmiStruct->HandlerType, (UINT8 *)SmiHandlerStruct + SmiHandlerStruct->ContextBufferOffset, SmiHandlerStruct->ContextBufferSize); } Print(L">\n"); ImageStruct = GetImageFromRef((UINTN)SmiHandlerStruct->ImageRef); NameString = GetDriverNameString (ImageStruct); Print(L" <Module RefId=\"0x%x\" Name=\"%a\">\n", SmiHandlerStruct->ImageRef, NameString); if ((ImageStruct != NULL) && (ImageStruct->PdbStringOffset != 0)) { Print(L" <Pdb>%a</Pdb>\n", (UINT8 *)ImageStruct + ImageStruct->PdbStringOffset); } Print(L" </Module>\n"); Print(L" <Handler Address=\"0x%lx\">\n", SmiHandlerStruct->Handler); if (ImageStruct != NULL) { Print(L" <RVA>0x%x</RVA>\n", (UINTN) (SmiHandlerStruct->Handler - ImageStruct->ImageBase)); } Print(L" </Handler>\n", SmiHandlerStruct->Handler); Print(L" <Caller Address=\"0x%lx\">\n", SmiHandlerStruct->CallerAddr); if (ImageStruct != NULL) { Print(L" <RVA>0x%x</RVA>\n", (UINTN) (SmiHandlerStruct->CallerAddr - ImageStruct->ImageBase)); } Print(L" </Caller>\n", SmiHandlerStruct->Handler); SmiHandlerStruct = (VOID *)((UINTN)SmiHandlerStruct + SmiHandlerStruct->Length); Print(L" </SmiHandler>\n"); } Print(L" </SmiEntry>\n"); } SmiStruct = (VOID *)((UINTN)SmiStruct + SmiStruct->Header.Length); } return; }
/** Get a human readable name for an image. The following methods will be tried orderly: 1. Image PDB 2. FFS UI section 3. Image GUID @param[in] ImageStruct Point to the image structure. @return The resulting Ascii name string is stored in the mNameString global array. **/ CHAR8 * GetDriverNameString ( IN SMM_CORE_IMAGE_DATABASE_STRUCTURE *ImageStruct ) { EFI_STATUS Status; CHAR16 *NameString; UINTN StringSize; if (ImageStruct == NULL) { return "???"; } // // Method 1: Get the name string from image PDB // if (ImageStruct->PdbStringOffset != 0) { GetShortPdbFileName ((CHAR8 *) ((UINTN) ImageStruct + ImageStruct->PdbStringOffset), mNameString); return mNameString; } if (!IsZeroGuid (&ImageStruct->FileGuid)) { // // Try to get the image's FFS UI section by image GUID // NameString = NULL; StringSize = 0; Status = GetSectionFromAnyFv ( &ImageStruct->FileGuid, EFI_SECTION_USER_INTERFACE, 0, (VOID **) &NameString, &StringSize ); if (!EFI_ERROR (Status)) { // // Method 2: Get the name string from FFS UI section // if (StrLen (NameString) > PROFILE_NAME_STRING_LENGTH) { NameString[PROFILE_NAME_STRING_LENGTH] = 0; } UnicodeStrToAsciiStrS (NameString, mNameString, sizeof (mNameString)); FreePool (NameString); return mNameString; } } // // Method 3: Get the name string from image GUID // AsciiSPrint (mNameString, sizeof (mNameString), "%g", &ImageStruct->FileGuid); return mNameString; }
/** Stop this driver on ControllerHandle. Support stopping any child handles created by this driver. @param This Protocol instance pointer. @param ControllerHandle Handle of device to stop driver on @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of children is zero stop the entire bus driver. @param ChildHandleBuffer List of Child Handles to Stop. @retval EFI_SUCCESS This driver is removed ControllerHandle @retval other This driver was not removed from this device **/ EFI_STATUS EFIAPI PartitionDriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; UINTN Index; EFI_BLOCK_IO_PROTOCOL *BlockIo; EFI_BLOCK_IO2_PROTOCOL *BlockIo2; BOOLEAN AllChildrenStopped; PARTITION_PRIVATE_DATA *Private; EFI_DISK_IO_PROTOCOL *DiskIo; EFI_GUID *TypeGuid; BlockIo = NULL; BlockIo2 = NULL; Private = NULL; if (NumberOfChildren == 0) { // // In the case of re-entry of the PartitionDriverBindingStop, the // NumberOfChildren may not reflect the actual number of children on the // bus driver. Hence, additional check is needed here. // if (HasChildren (ControllerHandle)) { DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: Still has child.\n")); return EFI_DEVICE_ERROR; } // // Close the bus driver // gBS->CloseProtocol ( ControllerHandle, &gEfiDiskIoProtocolGuid, This->DriverBindingHandle, ControllerHandle ); // // Close Parent BlockIO2 if has. // gBS->CloseProtocol ( ControllerHandle, &gEfiDiskIo2ProtocolGuid, This->DriverBindingHandle, ControllerHandle ); gBS->CloseProtocol ( ControllerHandle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, ControllerHandle ); return EFI_SUCCESS; } AllChildrenStopped = TRUE; for (Index = 0; Index < NumberOfChildren; Index++) { gBS->OpenProtocol ( ChildHandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); // // Try to locate BlockIo2. // gBS->OpenProtocol ( ChildHandleBuffer[Index], &gEfiBlockIo2ProtocolGuid, (VOID **) &BlockIo2, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo); if (Private->InStop) { // // If the child handle is going to be stopped again during the re-entry // of DriverBindingStop, just do nothing. // break; } Private->InStop = TRUE; BlockIo->FlushBlocks (BlockIo); if (BlockIo2 != NULL) { Status = BlockIo2->FlushBlocksEx (BlockIo2, NULL); DEBUG((EFI_D_ERROR, "PartitionDriverBindingStop: FlushBlocksEx returned with %r\n", Status)); } else { Status = EFI_SUCCESS; } gBS->CloseProtocol ( ControllerHandle, &gEfiDiskIoProtocolGuid, This->DriverBindingHandle, ChildHandleBuffer[Index] ); if (IsZeroGuid (&Private->TypeGuid)) { TypeGuid = NULL; } else { TypeGuid = &Private->TypeGuid; } // // All Software protocols have be freed from the handle so remove it. // Remove the BlockIo Protocol if has. // Remove the BlockIo2 Protocol if has. // if (BlockIo2 != NULL) { // // Some device drivers might re-install the BlockIO(2) protocols for a // media change condition. Therefore, if the FlushBlocksEx returned with // EFI_MEDIA_CHANGED, just let the BindingStop fail to avoid potential // reference of already stopped child handle. // if (Status != EFI_MEDIA_CHANGED) { Status = gBS->UninstallMultipleProtocolInterfaces ( ChildHandleBuffer[Index], &gEfiDevicePathProtocolGuid, Private->DevicePath, &gEfiBlockIoProtocolGuid, &Private->BlockIo, &gEfiBlockIo2ProtocolGuid, &Private->BlockIo2, &gEfiPartitionInfoProtocolGuid, &Private->PartitionInfo, TypeGuid, NULL, NULL ); } } else { Status = gBS->UninstallMultipleProtocolInterfaces ( ChildHandleBuffer[Index], &gEfiDevicePathProtocolGuid, Private->DevicePath, &gEfiBlockIoProtocolGuid, &Private->BlockIo, &gEfiPartitionInfoProtocolGuid, &Private->PartitionInfo, TypeGuid, NULL, NULL ); } if (EFI_ERROR (Status)) { Private->InStop = FALSE; gBS->OpenProtocol ( ControllerHandle, &gEfiDiskIoProtocolGuid, (VOID **) &DiskIo, This->DriverBindingHandle, ChildHandleBuffer[Index], EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); } else { FreePool (Private->DevicePath); FreePool (Private); } if (EFI_ERROR (Status)) { AllChildrenStopped = FALSE; if (Status == EFI_MEDIA_CHANGED) { break; } } } if (!AllChildrenStopped) { return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** Measure GPT table data into TPM log. Caution: This function may receive untrusted input. The GPT partition table is external input, so this function should parse partition data carefully. @param TcgProtocol Pointer to the located TCG protocol instance. @param GptHandle Handle that GPT partition was installed. @retval EFI_SUCCESS Successfully measure GPT table. @retval EFI_UNSUPPORTED Not support GPT table on the given handle. @retval EFI_DEVICE_ERROR Can't get GPT table because device error. @retval EFI_OUT_OF_RESOURCES No enough resource to measure GPT table. @retval other error value **/ EFI_STATUS EFIAPI TcgMeasureGptTable ( IN EFI_TCG_PROTOCOL *TcgProtocol, IN EFI_HANDLE GptHandle ) { EFI_STATUS Status; EFI_BLOCK_IO_PROTOCOL *BlockIo; EFI_DISK_IO_PROTOCOL *DiskIo; EFI_PARTITION_TABLE_HEADER *PrimaryHeader; EFI_PARTITION_ENTRY *PartitionEntry; UINT8 *EntryPtr; UINTN NumberOfPartition; UINT32 Index; TCG_PCR_EVENT *TcgEvent; EFI_GPT_DATA *GptData; UINT32 EventSize; UINT32 EventNumber; EFI_PHYSICAL_ADDRESS EventLogLastEntry; if (mMeasureGptCount > 0) { return EFI_SUCCESS; } Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID**)&DiskIo); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } // // Read the EFI Partition Table Header // PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *) AllocatePool (BlockIo->Media->BlockSize); if (PrimaryHeader == NULL) { return EFI_OUT_OF_RESOURCES; } Status = DiskIo->ReadDisk ( DiskIo, BlockIo->Media->MediaId, 1 * BlockIo->Media->BlockSize, BlockIo->Media->BlockSize, (UINT8 *)PrimaryHeader ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n")); FreePool (PrimaryHeader); return EFI_DEVICE_ERROR; } // // Read the partition entry. // EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); if (EntryPtr == NULL) { FreePool (PrimaryHeader); return EFI_OUT_OF_RESOURCES; } Status = DiskIo->ReadDisk ( DiskIo, BlockIo->Media->MediaId, MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry, EntryPtr ); if (EFI_ERROR (Status)) { FreePool (PrimaryHeader); FreePool (EntryPtr); return EFI_DEVICE_ERROR; } // // Count the valid partition // PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr; NumberOfPartition = 0; for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) { NumberOfPartition++; } PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry); } // // Prepare Data for Measurement // EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR)); if (TcgEvent == NULL) { FreePool (PrimaryHeader); FreePool (EntryPtr); return EFI_OUT_OF_RESOURCES; } TcgEvent->PCRIndex = 5; TcgEvent->EventType = EV_EFI_GPT_EVENT; TcgEvent->EventSize = EventSize; GptData = (EFI_GPT_DATA *) TcgEvent->Event; // // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition // CopyMem ((UINT8 *)GptData, (UINT8*)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER)); GptData->NumberOfPartitions = NumberOfPartition; // // Copy the valid partition entry // PartitionEntry = (EFI_PARTITION_ENTRY*)EntryPtr; NumberOfPartition = 0; for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { if (!IsZeroGuid (&PartitionEntry->PartitionTypeGUID)) { CopyMem ( (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry, (UINT8 *)PartitionEntry, PrimaryHeader->SizeOfPartitionEntry ); NumberOfPartition++; } PartitionEntry =(EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry); } // // Measure the GPT data // EventNumber = 1; Status = TcgProtocol->HashLogExtendEvent ( TcgProtocol, (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData, (UINT64) TcgEvent->EventSize, TPM_ALG_SHA, TcgEvent, &EventNumber, &EventLogLastEntry ); if (!EFI_ERROR (Status)) { mMeasureGptCount++; } FreePool (PrimaryHeader); FreePool (EntryPtr); FreePool (TcgEvent); return Status; }