Пример #1
0
EFI_STATUS
EFIAPI
UnlockFlashComponents (
  IN      EFI_SPI_PROTOCOL      *This,
  IN      UINT8                 UnlockCmdOpcodeIndex
  )
/*++

Routine Description:

  Issue unlock command to disable block protection, this only needs to be done once per SPI power on

Arguments:

  This                      A pointer to "EFI_SPI_PROTOCOL" for issuing commands
  UnlockCmdOpcodeIndex      The index of the Unlock command

Returns:

  EFI_SUCCESS               UnLock operation succeed.
  EFI_DEVICE_ERROR          Device error, operation failed.

--*/
{
  EFI_STATUS    Status;
  SPI_INSTANCE  *SpiInstance;
  UINT8         SpiStatus;

  if (UnlockCmdOpcodeIndex >= SPI_NUM_OPCODE) {
    return EFI_UNSUPPORTED;
  }

  SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);

  //
  // Issue unlock command to disable block protection, this only needs to be done once per SPI power on
  //
  SpiStatus = 0;
  //
  // Issue unlock command to the flash component 1 at first
  //
  Status = SpiProtocolExecute (
            This,
            UnlockCmdOpcodeIndex,
            SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_ENABLE ? 0 : 1,
            TRUE,
            TRUE,
            TRUE,
            (UINTN) 0,
            sizeof (SpiStatus),
            &SpiStatus,
            EnumSpiRegionAll
            );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Unlock flash component 1 fail!\n"));
    return Status;
  }

  return EFI_SUCCESS;
}
Пример #2
0
EFI_STATUS
EFIAPI
SpiProtocolInit (
  IN EFI_SPI_PROTOCOL       *This,
  IN SPI_INIT_TABLE         *InitTable
  )
/*++

Routine Description:

  Initialize the host controller to execute SPI command.

Arguments:

  This                    Pointer to the EFI_SPI_PROTOCOL instance.
  InitTable               Initialization data to be programmed into the SPI host controller.

Returns:

  EFI_SUCCESS             Initialization completed.
  EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.
  EFI_INVALID_PARAMETER   Bad input parameters.
  EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values
--*/
{
  EFI_STATUS    Status;
  UINT8         Index;
  UINT16        OpcodeType;
  SPI_INSTANCE  *SpiInstance;
  BOOLEAN       MultiPartitionIsSupported;
  UINTN         PchRootComplexBar;
  UINT8         SFDPCmdOpcodeIndex;
  UINT8         UnlockCmdOpcodeIndex;
  UINT8         ReadDataCmdOpcodeIndex;
  UINT8         FlashPartId[3];

  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
  PchRootComplexBar = SpiInstance->PchRootComplexBar;

  if (InitTable != NULL) {
    //
    // Copy table into SPI driver Private data structure
    //
    CopyMem (
      &SpiInstance->SpiInitTable,
      InitTable,
      sizeof (SPI_INIT_TABLE)
      );
  } else {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Check if the SPI interface has been locked-down.
  //
  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
    ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);
    return EFI_ACCESS_DENIED;
  }
  //
  // Clear all the status bits for status regs.
  //
  MmioOr16 (
    (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
    (UINT16) ((B_QNC_RCRB_SPIS_CDS | B_QNC_RCRB_SPIS_BAS))
    );
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);

  //
  // Set the Prefix Opcode registers.
  //
  MmioWrite16 (
    PchRootComplexBar + R_QNC_RCRB_SPIPREOP,
    (SpiInstance->SpiInitTable.PrefixOpcode[1] << 8) | InitTable->PrefixOpcode[0]
    );
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIPREOP);

  //
  // Set Opcode Type Configuration registers.
  //
  for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) {
    switch (SpiInstance->SpiInitTable.OpcodeMenu[Index].Type) {
    case EnumSpiOpcodeRead:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_READ << (Index * 2));
      break;
    case EnumSpiOpcodeWrite:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_WRITE << (Index * 2));
      break;
    case EnumSpiOpcodeWriteNoAddr:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE << (Index * 2));
      break;
    default:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_READ << (Index * 2));
      break;
    }
  }
  MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE, OpcodeType);
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE);

  //
  // Setup the Opcode Menu registers.
  //
  ReadDataCmdOpcodeIndex = SPI_NUM_OPCODE;
  SFDPCmdOpcodeIndex = SPI_NUM_OPCODE;
  UnlockCmdOpcodeIndex = SPI_NUM_OPCODE;
  for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
    MmioWrite8 (
      PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index,
      SpiInstance->SpiInitTable.OpcodeMenu[Index].Code
      );
    MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index);
    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
      Status = SpiProtocolExecute (
                This,
                Index,
                0,
                TRUE,
                TRUE,
                FALSE,
                (UINTN) 0,
                3,
                FlashPartId,
                EnumSpiRegionDescriptor
                );
      if (EFI_ERROR (Status)) {
        return Status;
      }
      if (FlashPartId[0] != SpiInstance->SpiInitTable.VendorId  ||
          FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0 ||
          FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1) {
        return EFI_INVALID_PARAMETER;
      }
    }

    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||
        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||
        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {
      ReadDataCmdOpcodeIndex = Index;
    }

    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDiscoveryParameters) {
      SFDPCmdOpcodeIndex = Index;
    }

    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
      UnlockCmdOpcodeIndex = Index;
    }
  }

  MultiPartitionIsSupported = FALSE;

  Status = UnlockFlashComponents (
            This,
            UnlockCmdOpcodeIndex
            );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Unlock flash components fail!\n"));
  }

  SpiPhaseInit ();
  FillOutPublicInfoStruct (SpiInstance);
  SpiInstance->InitDone = TRUE;
  return EFI_SUCCESS;
}