/** ReadyToBoot callback to send BlockSid command. @param Event Pointer to this event @param Context Event handler private Data **/ VOID EFIAPI ReadyToBootCallback ( IN EFI_EVENT Event, IN VOID *Context ) { OPAL_DRIVER_DEVICE *Itr; TCG_RESULT Result; OPAL_SESSION Session; UINT32 PpStorageFlag; gBS->CloseEvent (Event); PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags (); if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) { // // Send BlockSID command to each Opal disk // Itr = mOpalDriver.DeviceList; while (Itr != NULL) { if (Itr->OpalDisk.SupportedAttributes.BlockSid) { ZeroMem(&Session, sizeof(Session)); Session.Sscp = Itr->OpalDisk.Sscp; Session.MediaId = Itr->OpalDisk.MediaId; Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId; Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE if (Result != TcgResultSuccess) { DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n")); break; } } Itr = Itr->Next; } } }
/** Dispatch function for a Software SMI handler. @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). @param[in] RegisterContext Points to an optional handler context which was specified when the handler was registered. @param[in, out] CommBuffer A pointer to a collection of Data in memory that will be conveyed from a non-SMM environment into an SMM environment. @param[in, out] CommBufferSize The Size of the CommBuffer. @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers should still be called. @retval Others Other execution results. **/ EFI_STATUS EFIAPI SmmUnlockOpalPassword ( IN EFI_HANDLE DispatchHandle, IN CONST VOID *RegisterContext, IN OUT VOID *CommBuffer, IN OUT UINTN *CommBufferSize ) { EFI_STATUS Status; OPAL_SMM_DEVICE *OpalDev; LIST_ENTRY *Entry; UINT8 BaseClassCode; UINT8 SubClassCode; UINT8 ProgInt; TCG_RESULT Result; UINT8 SataCmdSt; UINT8 *StorePcieConfDataList[16]; UINTN RpBase; UINTN MemoryBase; UINTN MemoryLength; OPAL_SESSION Session; BOOLEAN BlockSidSupport; ZeroMem (StorePcieConfDataList, sizeof (StorePcieConfDataList)); Status = EFI_DEVICE_ERROR; // // try to unlock all locked hdd disks. // for (Entry = mSmmDeviceList.ForwardLink; Entry != &mSmmDeviceList; Entry = Entry->ForwardLink) { OpalDev = BASE_CR(Entry, OPAL_SMM_DEVICE, Link); RpBase = 0; SataCmdSt = 0; /// /// Configure RootPort for PCIe AHCI/NVME devices. /// if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) { /// /// Save original RootPort configuration space to heap /// RpBase = SaveRestoreRootportConfSpace ( OpalDev, TRUE, StorePcieConfDataList ); MemoryBase = mNvmeContext.Nbar; MemoryLength = 0; ConfigureRootPortForPcieNand (RpBase, OpalDev->BusNum, (UINT32) MemoryBase, (UINT32) MemoryLength); /// /// Enable PCIE decode for RootPort /// SataCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD); PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0x6); } else { SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD)); PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), 0x6); } BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0B)); SubClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0A)); ProgInt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x09)); if (BaseClassCode != PCI_CLASS_MASS_STORAGE) { Status = EFI_INVALID_PARAMETER; break; } Status = EFI_DEVICE_ERROR; if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_SATA) { if ((SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) || (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID)) { Status = GetAhciBaseAddress (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "GetAhciBaseAddress error, Status: %r\n", Status)); goto done; } Status = AhciModeInitialize ((UINT8)OpalDev->SataPort); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "AhciModeInitialize error, Status: %r\n", Status)); goto done; } } else { DEBUG ((DEBUG_ERROR, "SubClassCode not support for SATA device\n")); } } else if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) { if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) { if (ProgInt != PCI_IF_NVMHCI) { DEBUG ((DEBUG_ERROR, "PI not support, skipped\n")); Status = EFI_NOT_FOUND; goto done; } mNvmeContext.PciBase = PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0); mNvmeContext.NvmeInitWaitTime = 0; mNvmeContext.Nsid = OpalDev->NvmeNamespaceId; Status = NvmeControllerInit (&mNvmeContext); } else { DEBUG ((DEBUG_ERROR, "SubClassCode not support for NVME device\n")); } } else { DEBUG ((DEBUG_ERROR, "Invalid Devicetype\n")); goto done; } Status = EFI_DEVICE_ERROR; BlockSidSupport = FALSE; if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) { ZeroMem(&Session, sizeof(Session)); Session.Sscp = &OpalDev->Sscp; Session.MediaId = 0; Session.OpalBaseComId = OpalDev->OpalBaseComId; Result = OpalSupportUnlock (&Session, OpalDev->Password, OpalDev->PasswordLength, NULL); if (Result == TcgResultSuccess) { Status = EFI_SUCCESS; } } if (mSendBlockSID && BlockSidSupport) { Result = OpalBlockSid (&Session, TRUE); if (Result != TcgResultSuccess) { break; } } if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) { if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) { Status = NvmeControllerExit (&mNvmeContext); } } done: if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) { ASSERT (RpBase != 0); PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0); RpBase = SaveRestoreRootportConfSpace ( OpalDev, FALSE, // restore StorePcieConfDataList ); PciWrite8 (RpBase + NVME_PCIE_PCICMD, SataCmdSt); } else { PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), SataCmdSt); } if (EFI_ERROR (Status)) { break; } } return Status; }