Exemplo n.º 1
0
/**
  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;
}
Exemplo n.º 2
0
/**
  Check if disk is locked, show popup window and ask for password if it is

  @param[in]       Dev          The device which need to be unlock.

**/
VOID
OpalDriverRequestPassword (
  OPAL_DRIVER_DEVICE       *Dev
  )
{
  UINT8               Count;
  BOOLEAN             IsEnabled;
  CHAR8               *Password;
  UINT32              PasswordLen;
  TCG_RESULT          Ret;
  EFI_INPUT_KEY       Key;
  OPAL_SESSION        Session;
  BOOLEAN             PressEsc;
  BOOLEAN             Locked;

  if (Dev == NULL) {
    return;
  }

  Count = 0;

  IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);
  if (IsEnabled) {
    ZeroMem(&Session, sizeof(Session));
    Session.Sscp = Dev->OpalDisk.Sscp;
    Session.MediaId = Dev->OpalDisk.MediaId;
    Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;

    Locked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);

    while (Count < MAX_PASSWORD_TRY_COUNT) {
      Password = OpalDriverPopUpHddPassword (Dev, &PressEsc);
      if (PressEsc) {
        if (Locked) {
          //
          // Current device in the lock status and
          // User not input password and press ESC,
          // keep device in lock status and continue boot.
          //
          do {
            CreatePopUp (
                    EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
                    &Key,
                    L"Press ENTER to skip password, Press ESC to input password",
                    NULL
                    );
          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));

          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
            gST->ConOut->ClearScreen(gST->ConOut);
            //
            // Keep lock and continue boot.
            //
            return;
          } else {
            //
            // Let user input password again.
            //
            continue;
          }
        } else {
          //
          // Current device in the unlock status and
          // User not input password and press ESC,
          // Shutdown the device.
          //
          do {
            CreatePopUp (
                    EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
                    &Key,
                    L"Press ENTER to shutdown, Press ESC to input password",
                    NULL
                    );
          } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));

          if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
            gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
          } else {
            //
            // Let user input password again.
            //
            continue;
          }
        }
      }

      if (Password == NULL) {
        Count ++;
        continue;
      }
      PasswordLen = (UINT32) AsciiStrLen(Password);

      if (Locked) {
        Ret = OpalSupportUnlock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
      } else {
        Ret = OpalSupportLock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
        if (Ret == TcgResultSuccess) {
          Ret = OpalSupportUnlock(&Session, Password, PasswordLen, Dev->OpalDevicePath);
        }
      }

      if (Password != NULL) {
        ZeroMem (Password, PasswordLen);
        FreePool (Password);
      }

      if (Ret == TcgResultSuccess) {
        break;
      }

      Count++;

      do {
        CreatePopUp (
                  EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
                  &Key,
                  L"Invalid password.",
                  L"Press ENTER to retry",
                  NULL
                  );
      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
    }

    if (Count >= MAX_PASSWORD_TRY_COUNT) {
      do {
        CreatePopUp (
                EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
                &Key,
                L"Opal password retry count exceeds the limit. Must shutdown!",
                L"Press ENTER to shutdown",
                NULL
                );
      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);

      gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
    }
  }
}