예제 #1
0
파일: TisPc.c 프로젝트: B-Rich/edk2
/**
  Get BurstCount by reading the burstCount field of a TIS regiger 
  in the time of default TIS_TIMEOUT_D.

  @param[in]  TisReg                Pointer to TIS register.
  @param[out] BurstCount            Pointer to a buffer to store the got BurstConut.

  @retval     EFI_SUCCESS           Get BurstCount.
  @retval     EFI_INVALID_PARAMETER TisReg is NULL or BurstCount is NULL.
  @retval     EFI_TIMEOUT           BurstCount can't be got in time.
**/
EFI_STATUS
EFIAPI
TisPcReadBurstCount (
  IN      TIS_PC_REGISTERS_PTR      TisReg,
     OUT  UINT16                    *BurstCount
  )
{
  UINT32                            WaitTime;
  UINT8                             DataByte0;
  UINT8                             DataByte1;

  if (BurstCount == NULL || TisReg == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  WaitTime = 0;
  do {
    //
    // TIS_PC_REGISTERS_PTR->burstCount is UINT16, but it is not 2bytes aligned,
    // so it needs to use MmioRead8 to read two times
    //
    DataByte0   = MmioRead8 ((UINTN)&TisReg->BurstCount);
    DataByte1   = MmioRead8 ((UINTN)&TisReg->BurstCount + 1);
    *BurstCount = (UINT16)((DataByte1 << 8) + DataByte0);
    if (*BurstCount != 0) {
      return EFI_SUCCESS;
    }
    MicroSecondDelay (30);
    WaitTime += 30;
  } while (WaitTime < TIS_TIMEOUT_D);

  return EFI_TIMEOUT;
}
예제 #2
0
EFI_STATUS
IdentifyPL031 (
  VOID
  )
{
  EFI_STATUS    Status;

  // Check if this is a PrimeCell Peripheral
  if (  (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID0) != 0x0D)
      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID1) != 0xF0)
      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID2) != 0x05)
      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PCELL_ID3) != 0xB1)) {
    Status = EFI_NOT_FOUND;
    goto EXIT;
  }

  // Check if this PrimeCell Peripheral is the PL031 Real Time Clock
  if (  (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID0) != 0x31)
      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID1) != 0x10)
      || ((MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID2) & 0xF) != 0x04)
      || (MmioRead8 (mPL031RtcBase + PL031_RTC_PERIPH_ID3) != 0x00)) {
    Status = EFI_NOT_FOUND;
    goto EXIT;
  }

  Status = EFI_SUCCESS;

  EXIT:
  return Status;
}
예제 #3
0
CHAR8
EFIAPI
GdbGetChar (
  VOID
  )
{
  UINT32  LSR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_LSR_REG;
  UINT32  RBR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_RBR_REG;
  CHAR8   Char;

  while ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_EMPTY);
  Char = MmioRead8(RBR);

  return Char;
}
예제 #4
0
파일: PL061Gpio.c 프로젝트: pmj/edk2
/**

Routine Description:

  Gets the mode (function) of a GPIO pin

Arguments:

  This  - pointer to protocol
  Gpio  - which pin
  Mode  - pointer to output mode value

Returns:

  EFI_SUCCESS           - mode value retrieved
  EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range

**/
EFI_STATUS
EFIAPI
GetMode (
  IN  EMBEDDED_GPIO       *This,
  IN  EMBEDDED_GPIO_PIN   Gpio,
  OUT EMBEDDED_GPIO_MODE  *Mode
  )
{
  EFI_STATUS    Status = EFI_SUCCESS;
  UINTN         Index, Offset, RegisterBase;

  Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
  ASSERT_EFI_ERROR (Status);

  // Check for errors
  if (Mode == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  // Check if it is input or output
  if (MmioRead8 (RegisterBase + PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Offset)) {
    // Pin set to output
    if (PL061GetPins (RegisterBase, GPIO_PIN_MASK(Offset))) {
      *Mode = GPIO_MODE_OUTPUT_1;
    } else {
      *Mode = GPIO_MODE_OUTPUT_0;
    }
  } else {
    // Pin set to input
    *Mode = GPIO_MODE_INPUT;
  }

  return EFI_SUCCESS;
}
예제 #5
0
파일: Platform.c 프로젝트: shijunjing/edk2
VOID
ClearP2PBusMaster(
  )
{
  UINT8             Command;
  UINT8             Index;

  for (Index = 0; Index < sizeof(mPciBm)/sizeof(EFI_PCI_BUS_MASTER); Index++) {
    Command = MmioRead8 (
                MmPciAddress (0,
                  DEFAULT_PCI_BUS_NUMBER_PCH,
                  mPciBm[Index].Device,
                  mPciBm[Index].Function,
                  PCI_COMMAND_OFFSET
                )
              );
    Command &= ~EFI_PCI_COMMAND_BUS_MASTER;
    MmioWrite8 (
      MmPciAddress (0,
        DEFAULT_PCI_BUS_NUMBER_PCH,
        mPciBm[Index].Device,
        mPciBm[Index].Function,
        PCI_COMMAND_OFFSET
      ),
      Command
    );
  }
}
예제 #6
0
/**
  Read data from serial device and save the datas in buffer.

  @param  Buffer           Point of data buffer which need to be writed.
  @param  NumberOfBytes    Number of output bytes which are cached in Buffer.

  @retval 0                Read data failed.
  @retval !0               Aactual number of bytes read from serial device.

**/
UINTN
EFIAPI
SerialPortRead (
  OUT UINT8     *Buffer,
  IN  UINTN     NumberOfBytes
)
{
  UINT32  LSR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_LSR_REG;
  UINT32  RBR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_RBR_REG;
  UINTN   Count;
    
  for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
    while ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_EMPTY);
    *Buffer = MmioRead8(RBR);
  }

  return NumberOfBytes;
}
예제 #7
0
/**
  Reads an 8-bit PCI configuration register.

  Reads and returns the 8-bit PCI configuration register specified by Address.
  This function must guarantee that all PCI read and write operations are
  serialized.

  If Address > 0x0FFFFFFF, then ASSERT().

  @param  Address Address that encodes the PCI Bus, Device, Function and
                  Register.

  @return The read value from the PCI configuration register.

**/
UINT8
EFIAPI
PciExpressRead8 (
  IN      UINTN                     Address
  )
{
  ASSERT_INVALID_PCI_ADDRESS (Address);
  return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
}
예제 #8
0
파일: CpuIoPei.c 프로젝트: shijunjing/edk2
/**
  8-bit memory read operations.

  @param[in] PeiServices  An indirect pointer to the PEI Services Table published
                          by the PEI Foundation.
  @param[in] This         Pointer to local data for the interface.
  @param[in] Address      The physical address of the access.

  @return  An 8-bit value returned from the memory space.

**/
UINT8
EFIAPI
CpuMemRead8 (
  IN CONST EFI_PEI_SERVICES    **PeiServices,
  IN CONST EFI_PEI_CPU_IO_PPI  *This,
  IN UINT64                    Address
  )
{
  return MmioRead8 ((UINTN)Address);
}
예제 #9
0
파일: PL061Gpio.c 프로젝트: pmj/edk2
STATIC
UINTN
EFIAPI
PL061GetPins (
  IN UINTN Address,
  IN UINTN Mask
  )
{
  return MmioRead8 (PL061EffectiveAddress (Address, Mask));
}
예제 #10
0
파일: TisPc.c 프로젝트: B-Rich/edk2
/**
  Check whether TPM chip exist.

  @param[in] TisReg  Pointer to TIS register.

  @retval    TRUE    TPM chip exists.
  @retval    FALSE   TPM chip is not found.
**/
BOOLEAN
TisPcPresenceCheck (
  IN      TIS_PC_REGISTERS_PTR      TisReg
  )
{
  UINT8                             RegRead;
  
  RegRead = MmioRead8 ((UINTN)&TisReg->Access);
  return (BOOLEAN)(RegRead != (UINT8)-1);
}
예제 #11
0
파일: CpuIoPei.c 프로젝트: shijunjing/edk2
/**
  Reads memory-mapped registers.

  @param[in]  PeiServices  An indirect pointer to the PEI Services Table
                           published by the PEI Foundation.
  @param[in]  This         Pointer to local data for the interface.
  @param[in]  Width        The width of the access. Enumerated in bytes.
  @param[in]  Address      The physical address of the access.
  @param[in]  Count        The number of accesses to perform.
  @param[out] Buffer       A pointer to the buffer of data.

  @retval EFI_SUCCESS            The function completed successfully.
  @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
                                 and Count is not valid for this EFI system.

**/
EFI_STATUS
EFIAPI
CpuMemoryServiceRead (
  IN  CONST EFI_PEI_SERVICES    **PeiServices,
  IN  CONST EFI_PEI_CPU_IO_PPI  *This,
  IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
  IN  UINT64                    Address,
  IN  UINTN                     Count,
  OUT VOID                      *Buffer
  )
{
  EFI_STATUS                Status;
  UINT8                     InStride;
  UINT8                     OutStride;
  EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
  BOOLEAN                   Aligned;
  UINT8                     *Uint8Buffer;

  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  InStride = mInStride[Width];
  OutStride = mOutStride[Width];
  OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
  Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    if (OperationWidth == EfiPeiCpuIoWidthUint8) {
      *Uint8Buffer = MmioRead8 ((UINTN)Address);
    } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
      if (Aligned) {
        *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
      } else {
        WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
      }
    } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
      if (Aligned) {
        *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
      } else {
        WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
      }
    } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
      if (Aligned) {
        *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
      } else {
        WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
      }
    }
  }
  return EFI_SUCCESS;
}
예제 #12
0
VOID
EFIAPI
GdbPutChar (
  IN  CHAR8   Char
  )
{
  UINT32  LSR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_LSR_REG;
  UINT32  THR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_THR_REG;

  while ((MmioRead8(LSR) & UART_LSR_TX_FIFO_E_MASK) == UART_LSR_TX_FIFO_E_NOT_EMPTY);
  MmioWrite8(THR, Char);
}
예제 #13
0
파일: PL061Gpio.c 프로젝트: jforissier/uefi
/**

Routine Description:

  Gets the mode (function) of a GPIO pin

Arguments:

  This  - pointer to protocol
  Gpio  - which pin
  Mode  - pointer to output mode value

Returns:

  EFI_SUCCESS           - mode value retrieved
  EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range

**/
EFI_STATUS
EFIAPI
GetMode (
  IN  EMBEDDED_GPIO       *This,
  IN  EMBEDDED_GPIO_PIN   Gpio,
  OUT EMBEDDED_GPIO_MODE  *Mode
  )
{
  EFI_STATUS    Status;
  UINTN         Index, Offset, RegisterBase;

  Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
  if (EFI_ERROR (Status))
    return Status;

  // Initialize the hardware if not already done
  if (!mPL061Initialized) {
    Status = PL061Initialize();
    if (EFI_ERROR(Status)) {
      return Status;
    }
  }

  // Check if it is input or output
  if (MmioRead8 (RegisterBase + PL061_GPIO_DIR_REG) & GPIO_PIN_MASK(Offset)) {
    // Pin set to output
    if (MmioRead8 (RegisterBase + PL061_GPIO_DATA_REG + (GPIO_PIN_MASK(Offset) << 2))) {
      *Mode = GPIO_MODE_OUTPUT_1;
    } else {
      *Mode = GPIO_MODE_OUTPUT_0;
    }
  } else {
    // Pin set to input
    *Mode = GPIO_MODE_INPUT;
  }

  return EFI_SUCCESS;
}
예제 #14
0
/**
  Check to see if any data is avaiable to be read from the debug device.

  @retval EFI_SUCCESS       At least one byte of data is avaiable to be read
  @retval EFI_NOT_READY     No data is avaiable to be read
  @retval EFI_DEVICE_ERROR  The serial device is not functioning properly

**/
BOOLEAN
EFIAPI
SerialPortPoll (
  VOID
  )
{
  UINT32 LSR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_LSR_REG;

  if ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_NOT_EMPTY) {
    return TRUE;
  } else {
    return FALSE;
  }
}
예제 #15
0
/**
  Reads a 8-bit I/O port.

  Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned.
  This function must guarantee that all I/O read and write operations are
  serialized.

  @param  Port  The I/O port to read.

  @return The value read.

**/
UINT8
EFIAPI
IoRead8 (
  IN  UINT64                 Port
  )
{
  UINT64           Address;

  //
  // Add the 64MB aligned IO Port space to the IO address
  //
  Address = MAP_PORT_BASE_TO_MEM (Port);
  Address += PcdGet64(PcdIoBlockBaseAddressForIpf);

  return MmioRead8 (Address);
}
예제 #16
0
/**
  This routine return if dTPM (1.2 or 2.0) present.

  @retval TRUE  dTPM present
  @retval FALSE dTPM not present
**/
BOOLEAN
IsDtpmPresent (
    VOID
)
{
    UINT8                             RegRead;

    RegRead = MmioRead8 ((UINTN)PcdGet64 (PcdTpmBaseAddress));
    if (RegRead == 0xFF) {
        DEBUG ((EFI_D_ERROR, "DetectTpmDevice: Dtpm not present\n"));
        return FALSE;
    } else {
        DEBUG ((EFI_D_ERROR, "DetectTpmDevice: Dtpm present\n"));
        return TRUE;
    }
}
예제 #17
0
/**
  Write data to serial device.

  @param  Buffer           Point of data buffer which need to be writed.
  @param  NumberOfBytes    Number of output bytes which are cached in Buffer.

  @retval 0                Write data failed.
  @retval !0               Actual number of bytes writed to serial device.

**/
UINTN
EFIAPI
SerialPortWrite (
  IN UINT8     *Buffer,
  IN UINTN     NumberOfBytes
)
{
  UINT32  LSR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_LSR_REG;
  UINT32  THR = UartBase(PcdGet32(PcdOmap35xxConsoleUart)) + UART_THR_REG;
  UINTN   Count;
    
  for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
    while ((MmioRead8(LSR) & UART_LSR_TX_FIFO_E_MASK) == UART_LSR_TX_FIFO_E_NOT_EMPTY);
    MmioWrite8(THR, *Buffer);
  }

  return NumberOfBytes;
}
예제 #18
0
파일: Platform.c 프로젝트: shijunjing/edk2
VOID
SetAfterG3On (
  BOOLEAN Enable
  )
{
  UINT8             PmCon1;

  //
  // ICH handling portion
  //
  PmCon1 = MmioRead8 ( PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1 );
  PmCon1 &= ~B_PCH_PMC_GEN_PMCON_AFTERG3_EN;
  if (Enable) {
    PmCon1 |= B_PCH_PMC_GEN_PMCON_AFTERG3_EN;
  }
  MmioWrite8 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, PmCon1);

}
예제 #19
0
/**
  Reads I/O registers.

  The I/O operations are carried out exactly as requested. The caller is responsible
  for satisfying any alignment and I/O width restrictions that a PI System on a
  platform might require. For example on some platforms, width requests of
  EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
  be handled by the driver.

  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
  each of the Count operations that is performed.

  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
  incremented for each of the Count operations that is performed. The read or
  write operation is performed Count times on the same Address.

  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
  incremented for each of the Count operations that is performed. The read or
  write operation is performed Count times from the first element of Buffer.

  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
  @param[in]  Width    Signifies the width of the I/O or Memory operation.
  @param[in]  Address  The base address of the I/O operation.
  @param[in]  Count    The number of I/O operations to perform. The number of
                       bytes moved is Width size * Count, starting at Address.
  @param[out] Buffer   For read operations, the destination buffer to store the results.
                       For write operations, the source buffer from which to write data.

  @retval EFI_SUCCESS            The data was read from or written to the PI system.
  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
                                 and Count is not valid for this PI system.

**/
STATIC
EFI_STATUS
EFIAPI
CpuIoServiceRead (
  IN  EFI_CPU_IO2_PROTOCOL       *This,
  IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
  IN  UINT64                     Address,
  IN  UINTN                      Count,
  OUT VOID                       *Buffer
  )
{
  EFI_STATUS                 Status;
  UINT8                      InStride;
  UINT8                      OutStride;
  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
  UINT8                      *Uint8Buffer;

  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Address += PcdGet64 (PcdPciIoTranslation);

  //
  // Select loop based on the width of the transfer
  //
  InStride = mInStride[Width];
  OutStride = mOutStride[Width];
  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);

  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    if (OperationWidth == EfiCpuIoWidthUint8) {
      *Uint8Buffer = MmioRead8 ((UINTN)Address);
    } else if (OperationWidth == EfiCpuIoWidthUint16) {
      *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
    } else if (OperationWidth == EfiCpuIoWidthUint32) {
      *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
    }
  }

  return EFI_SUCCESS;
}
예제 #20
0
파일: TisPc.c 프로젝트: B-Rich/edk2
/**
  Check whether the value of a TPM chip register satisfies the input BIT setting.

  @param[in]  Register     Address port of register to be checked.
  @param[in]  BitSet       Check these data bits are set.
  @param[in]  BitClear     Check these data bits are clear.
  @param[in]  TimeOut      The max wait time (unit MicroSecond) when checking register.

  @retval     EFI_SUCCESS  The register satisfies the check bit.
  @retval     EFI_TIMEOUT  The register can't run into the expected status in time.
**/
EFI_STATUS
EFIAPI
TisPcWaitRegisterBits (
  IN      UINT8                     *Register,
  IN      UINT8                     BitSet,
  IN      UINT8                     BitClear,
  IN      UINT32                    TimeOut
  )
{
  UINT8                             RegRead;
  UINT32                            WaitTime;

  for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30){
    RegRead = MmioRead8 ((UINTN)Register);
    if ((RegRead & BitSet) == BitSet && (RegRead & BitClear) == 0)
      return EFI_SUCCESS;
    MicroSecondDelay (30);
  }
  return EFI_TIMEOUT;
}
예제 #21
0
파일: PL061Gpio.c 프로젝트: pmj/edk2
EFI_STATUS
PL061Identify (
  VOID
  )
{
  UINTN    Index;
  UINTN    RegisterBase;

  if (   (mPL061PlatformGpio->GpioCount == 0)
      || (mPL061PlatformGpio->GpioControllerCount == 0)) {
     return EFI_NOT_FOUND;
  }

  for (Index = 0; Index < mPL061PlatformGpio->GpioControllerCount; Index++) {
    if (mPL061PlatformGpio->GpioController[Index].InternalGpioCount != PL061_GPIO_PINS) {
      return EFI_INVALID_PARAMETER;
    }

    RegisterBase = mPL061PlatformGpio->GpioController[Index].RegisterBase;

    // Check if this is a PrimeCell Peripheral
    if (    (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID0) != 0x0D)
        ||  (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID1) != 0xF0)
        ||  (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID2) != 0x05)
        ||  (MmioRead8 (RegisterBase + PL061_GPIO_PCELL_ID3) != 0xB1)) {
      return EFI_NOT_FOUND;
    }

    // Check if this PrimeCell Peripheral is the PL061 GPIO
    if (    (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID0) != 0x61)
        ||  (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID1) != 0x10)
        ||  ((MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04)
        ||  (MmioRead8 (RegisterBase + PL061_GPIO_PERIPH_ID3) != 0x00)) {
      return EFI_NOT_FOUND;
    }
  }

  return EFI_SUCCESS;
}
예제 #22
0
EFIAPI
MmioReadBuffer8 (
  IN  UINTN       StartAddress,
  IN  UINTN       Length,
  OUT UINT8       *Buffer
  )
{
  UINT8   *ReturnBuffer;

  ASSERT ((Length - 1) <=  (MAX_ADDRESS - StartAddress));
  ASSERT ((Length - 1) <=  (MAX_ADDRESS - (UINTN) Buffer));

  ReturnBuffer = Buffer;

  while (Length-- > 0) {
    *(Buffer++) = MmioRead8 (StartAddress++);
  }

  return ReturnBuffer;
}
예제 #23
0
EFI_STATUS
SP805Identify (
  VOID
  )
{
  // Check if this is a PrimeCell Peripheral
  if (    (MmioRead8 (SP805_WDOG_PCELL_ID0) != 0x0D)
      ||  (MmioRead8 (SP805_WDOG_PCELL_ID1) != 0xF0)
      ||  (MmioRead8 (SP805_WDOG_PCELL_ID2) != 0x05)
      ||  (MmioRead8 (SP805_WDOG_PCELL_ID3) != 0xB1)) {
    return EFI_NOT_FOUND;
  }

  // Check if this PrimeCell Peripheral is the SP805 Watchdog Timer
  if (    (MmioRead8 (SP805_WDOG_PERIPH_ID0) != 0x05)
      ||  (MmioRead8 (SP805_WDOG_PERIPH_ID1) != 0x18)
      || ((MmioRead8 (SP805_WDOG_PERIPH_ID2) & 0x0000000F) != 0x04)
      ||  (MmioRead8 (SP805_WDOG_PERIPH_ID3) != 0x00)) {
    return EFI_NOT_FOUND;
  }

  return EFI_SUCCESS;
}
예제 #24
0
파일: PL061Gpio.c 프로젝트: jforissier/uefi
/**

Routine Description:

  Gets the state of a GPIO pin

Arguments:

  This  - pointer to protocol
  Gpio  - which pin to read
  Value - state of the pin

Returns:

  EFI_SUCCESS           - GPIO state returned in Value
  EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range
**/
EFI_STATUS
EFIAPI
Get (
  IN  EMBEDDED_GPIO     *This,
  IN  EMBEDDED_GPIO_PIN Gpio,
  OUT UINTN             *Value
  )
{
  EFI_STATUS    Status = EFI_SUCCESS;
  UINTN         Index, Offset, RegisterBase;

  Status = PL061Locate (Gpio, &Index, &Offset, &RegisterBase);
  if (EFI_ERROR (Status))
    goto EXIT;

  if (Value == NULL) {
    Status = EFI_INVALID_PARAMETER;
    goto EXIT;
  }

  // Initialize the hardware if not already done
  if (!mPL061Initialized) {
    Status = PL061Initialize();
    if (EFI_ERROR(Status)) {
      goto EXIT;
    }
  }

  if (MmioRead8 (RegisterBase + PL061_GPIO_DATA_REG + (GPIO_PIN_MASK(Offset) << 2))) {
    *Value = 1;
  } else {
    *Value = 0;
  }

  EXIT:
  return Status;
}
예제 #25
0
파일: CpuIo2Smm.c 프로젝트: kraxel/edk2
/**
  Reads memory-mapped registers.

  The I/O operations are carried out exactly as requested.  The caller is 
  responsible for any alignment and I/O width issues that the bus, device, 
  platform, or type of I/O might require.

  @param[in]  This     The EFI_SMM_CPU_IO2_PROTOCOL instance.
  @param[in]  Width    Signifies the width of the I/O operations.
  @param[in]  Address  The base address of the I/O operations.  The caller is 
                       responsible for aligning the Address if required. 
  @param[in]  Count    The number of I/O operations to perform.
  @param[out] Buffer   For read operations, the destination buffer to store 
                       the results.  For write operations, the source buffer 
                       from which to write data.

  @retval EFI_SUCCESS            The data was read from or written to the device.
  @retval EFI_UNSUPPORTED        The Address is not valid for this system.
  @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a 
                                 lack of resources

**/
EFI_STATUS
EFIAPI
CpuMemoryServiceRead (
  IN  CONST EFI_SMM_CPU_IO2_PROTOCOL  *This,
  IN  EFI_SMM_IO_WIDTH                Width,
  IN  UINT64                          Address,
  IN  UINTN                           Count,
  OUT VOID                            *Buffer
  )
{
  EFI_STATUS  Status;
  UINT8       Stride;
  UINT8       *Uint8Buffer;

  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  Stride = mStride[Width];
  for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
    if (Width == SMM_IO_UINT8) {
      *Uint8Buffer = MmioRead8 ((UINTN)Address);
    } else if (Width == SMM_IO_UINT16) {
      *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
    } else if (Width == SMM_IO_UINT32) {
      *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
    } else if (Width == SMM_IO_UINT64) {
      *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
    }
  }
  return EFI_SUCCESS;
}
예제 #26
0
파일: Smbus.c 프로젝트: B-Rich/edk2
STATIC
EFI_STATUS
I2CReadOneByte (
  UINT8 *Data
  )
{
  EFI_STATUS Status;

  //I2C bus status checking
  Status = WaitForBusBusy();
  if (EFI_ERROR(Status)) {
    return Status;
  }

  //Poll till Receive ready bit is set.
  Status = PollForStatus(RRDY);
  if (EFI_ERROR(Status)) {
    return Status;
  }

  *Data = MmioRead8(I2C_DATA);

  return EFI_SUCCESS;
}
예제 #27
0
/**
  Write data from buffer to debug device.

  Writes NumberOfBytes data bytes from Buffer to the debug device.
  The number of bytes actually written to the debug device is returned.
  If the return value is less than NumberOfBytes, then the write operation failed.
  If NumberOfBytes is zero, then return 0.

  @param  Handle           Debug port handle.
  @param  Buffer           Pointer to the data buffer to be written.
  @param  NumberOfBytes    Number of bytes to written to the debug device.

  @retval 0                NumberOfBytes is 0.
  @retval >0               The number of bytes written to the debug device.
                           If this value is less than NumberOfBytes, then the read operation failed.

**/
UINTN
EFIAPI
DebugPortWriteBuffer (
  IN   DEBUG_PORT_HANDLE    Handle,
  IN   UINT8                *Buffer,
  IN   UINTN                NumberOfBytes
  )
{
  USB_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;
  USB_DEBUG_PORT_REGISTER   *UsbDebugPortRegister;
  RETURN_STATUS             Status;
  UINT8                     Sent;
  UINTN                     Total;
  UINT8                     ReceivedPid;

  if (NumberOfBytes == 0 || Buffer == NULL) {
    return 0;
  }

  Sent  = 0;
  Total = 0;

  //
  // If Handle is NULL, it means memory is ready for use.
  // Use global variable to store handle value.
  //
  if (Handle == NULL) {
    UsbDebugPortHandle = &mUsbDebugPortHandle;
  } else {
    UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Handle;
  }

  if (NeedReinitializeHardware(UsbDebugPortHandle)) {
    Status = InitializeUsbDebugHardware (UsbDebugPortHandle);
    if (RETURN_ERROR(Status)) {
      return 0;
    }
  }

  UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(UINTN)(UsbDebugPortHandle->UsbDebugPortMemoryBase + UsbDebugPortHandle->DebugPortOffset);

  while ((Total < NumberOfBytes)) {
    if (NumberOfBytes - Total > USB_DEBUG_PORT_MAX_PACKET_SIZE) {
      Sent = USB_DEBUG_PORT_MAX_PACKET_SIZE;
    } else {
      Sent = (UINT8)(NumberOfBytes - Total);
    }

    Status = UsbDebugPortOut(UsbDebugPortRegister, Buffer + Total, Sent, OUTPUT_PID, 0x7F, 0x01, UsbDebugPortHandle->BulkOutToggle);

    if (RETURN_ERROR(Status)) {
      return Total;
    }

    ReceivedPid = (MmioRead8((UINTN)&UsbDebugPortRegister->ReceivedPid));
    //
    // If received a NAK_PID on write transaction, it means the usb debug device is busy and can not handle this transaction.
    // should send the packet again.
    //
    if (ReceivedPid == NAK_PID) {
      Sent = 0;
    } else {
      UsbDebugPortHandle->BulkOutToggle ^= 1;
    }
    Total += Sent;
  }
  return Total;
}
예제 #28
0
EFI_STATUS
SendSpiCmd (
  IN     EFI_SPI_PROTOCOL   *This,
  IN     UINT8              OpcodeIndex,
  IN     UINT8              PrefixOpcodeIndex,
  IN     BOOLEAN            DataCycle,
  IN     BOOLEAN            Atomic,
  IN     BOOLEAN            ShiftOut,
  IN     UINTN              Address,
  IN     UINT32             DataByteCount,
  IN OUT UINT8              *Buffer,
  IN     SPI_REGION_TYPE    SpiRegionType
  )
/*++

Routine Description:

  This function sends the programmed SPI command to the slave device.

Arguments:

  OpcodeIndex       Index of the command in the OpCode Menu.
  PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
  DataCycle         TRUE if the SPI cycle contains data
  Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
  ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
  Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
                    Region, this value specifies the offset from the Region Base; for BIOS Region,
                    this value specifies the offset from the start of the BIOS Image. In Non
                    Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
                    Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
                    Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
                    supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
                    the flash (in Non Descriptor Mode)
  DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
                    data transfer into multiple operations. This function ensures each operation does
                    not cross 256 byte flash address boundary.
                    *NOTE: if there is some SPI chip that has a stricter address boundary requirement
                    (e.g., its write page size is < 256 byte), then the caller cannot rely on this
                    function to cut the data transfer at proper address boundaries, and it's the
                    caller's reponsibility to pass in a properly cut DataByteCount parameter.
  Buffer            Data received or sent during the SPI cycle.
  SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
                    EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
                    Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
                    and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
                    to base of the 1st flash device (i.e., it is a Flash Linear Address).

Returns:

  EFI_SUCCESS             SPI command completes successfully.
  EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
  EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
  EFI_INVALID_PARAMETER   The parameters specified are not valid.

--*/
{
  UINT32        Index;
  SPI_INSTANCE  *SpiInstance;
  UINTN         HardwareSpiAddr;
  UINTN         SpiBiosSize;
  UINTN         BaseAddress;
  UINTN         LimitAddress;
  UINT32        SpiDataCount;
  UINT8         OpCode;
  SPI_OPERATION Operation;
  UINTN         PchRootComplexBar;

  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
  PchRootComplexBar = SpiInstance->PchRootComplexBar;
  SpiBiosSize       = SpiInstance->SpiInitTable.BiosSize;
  Operation         = SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Operation;
  OpCode            = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + OpcodeIndex);

  //
  // Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0
  //
  if (OpCode == 0 || SpiBiosSize == 0) {
    ASSERT (FALSE);
    return EFI_INVALID_PARAMETER;
  }

  SpiOffset2Physical (This, Address, SpiRegionType, &HardwareSpiAddr, &BaseAddress, &LimitAddress);
  //
  // Have direct access to BIOS region in Descriptor mode,
  //
  if (SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Type == EnumSpiOpcodeRead &&
      SpiRegionType == EnumSpiRegionBios) {
    CopyMem (
      Buffer,
      (UINT8 *) ((HardwareSpiAddr - BaseAddress) + (UINT32) (~(SpiBiosSize - 1))),
      DataByteCount
      );
    return EFI_SUCCESS;
  }
  //
  // DEBUG((EFI_D_ERROR, "SPIADDR %x, %x, %x, %x\n", Address, HardwareSpiAddr, BaseAddress,
  // LimitAddress));
  //
  if ((DataCycle == FALSE) && (DataByteCount > 0)) {
    DataByteCount = 0;
  }

  do {
    //
    // Trim at 256 byte boundary per operation,
    // - PCH SPI controller requires trimming at 4KB boundary
    // - Some SPI chips require trimming at 256 byte boundary for write operation
    // - Trimming has limited performance impact as we can read / write atmost 64 byte
    //   per operation
    //
    if (HardwareSpiAddr + DataByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
      SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
    } else {
      SpiDataCount = DataByteCount;
    }
    //
    // Calculate the number of bytes to shift in/out during the SPI data cycle.
    // Valid settings for the number of bytes duing each data portion of the
    // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
    //
    if (SpiDataCount >= 64) {
      SpiDataCount = 64;
    } else if ((SpiDataCount &~0x07) != 0) {
      SpiDataCount = SpiDataCount &~0x07;
    }
    //
    // If shifts data out, load data into the SPI data buffer.
    //
    if (ShiftOut) {
      for (Index = 0; Index < SpiDataCount; Index++) {
        MmioWrite8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index, Buffer[Index]);
        MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
      }
    }

    MmioWrite32 (
      (PchRootComplexBar + R_QNC_RCRB_SPIA),
      (UINT32) (HardwareSpiAddr & B_QNC_RCRB_SPIA_MASK)
      );
    MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIA);

    //
    // Execute the command on the SPI compatible mode
    //

    //
    // Clear error flags
    //
    MmioOr16 ((PchRootComplexBar + R_QNC_RCRB_SPIS), B_QNC_RCRB_SPIS_BAS);

    //
    // Initialte the SPI cycle
    //
    if (DataCycle) {
      MmioWrite16 (
        (PchRootComplexBar + R_QNC_RCRB_SPIC),
        ( (UINT16) (B_QNC_RCRB_SPIC_DC) | (UINT16) (((SpiDataCount - 1) << 8) & B_QNC_RCRB_SPIC_DBC) |
          (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
          (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
          (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
          (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
    } else {
      MmioWrite16 (
        (PchRootComplexBar + R_QNC_RCRB_SPIC),
        ( (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
          (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
          (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
          (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
    }

    MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIC);

    //
    // end of command execution
    //
    // Wait the SPI cycle to complete.
    //
    if (!WaitForSpiCycleComplete (This, TRUE)) {
      return EFI_DEVICE_ERROR;
    }
    //
    // If shifts data in, get data from the SPI data buffer.
    //
    if (!ShiftOut) {
      for (Index = 0; Index < SpiDataCount; Index++) {
        Buffer[Index] = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
      }
    }

    HardwareSpiAddr += SpiDataCount;
    Buffer += SpiDataCount;
    DataByteCount -= SpiDataCount;
  } while (DataByteCount > 0);

  return EFI_SUCCESS;
}
예제 #29
0
파일: S3Save.c 프로젝트: shijunjing/edk2
EFI_STATUS
SaveRuntimeScriptTable (
  VOID
  )
{
  SMM_PCI_IO_ADDRESS    PciAddress;
  UINT32                Data32;
  UINT16                Data16;
  UINT8                 Data8;
  UINT8                 Mask;
  UINTN                 Index;
  UINTN                 Offset;
  UINT8                 RegTable[] = {

	  //
    //Bus  ,   Dev,  Func,    DMI
	  //
      0x00 ,  0x00,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
	  //
      0x00 ,  0x08,  0x00,  0x00,  0x30,  0x00,  0x00,  0xa0,

	  //
    //Bus  ,   Dev,  Func,    LPC device
	  //
      0x00 ,  0x1F,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x00 ,  0x08,  0x00,  0x07,  0x00,  0x00,  0x90,  0x00,

	  //
    //Bus  ,   Dev,  Func,    PCIE device
	 //
      0x00 ,  0x1C,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0xC0 ,  0x83,  0x30,  0x00,  0x00,  0x00,  0x00,  0x00,

	  //
    //Bus  ,   Dev,  Func,    PCIE device
    //
	  0x00 ,  0x1C,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x03 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

	  //
    //Bus  ,   Dev,  Func,    SATA device
	  //
      0x00 ,  0x13,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0xf4 ,  0xab,  0x27,  0x10,  0xf1,  0x1d,  0x00,  0x40,

    //
    //Bus  ,   Dev,  Func,    EHCI device
    //
     0x00 ,  0x1D,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
     0x10 ,  0x88,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,

    //
    //Bus  ,   Dev,  Func,    SMBUS device
    //
     0x00 ,  0x1f,  0x03,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x10 ,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    SMBUS device
    //
      0x00 ,  0x1f,  0x03,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1
    //
      0x01 ,  0x00,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x58 ,  0x81,  0x18,  0x01,  0xb0,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1
    //
      0x01 ,  0x00,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1 function 1
    //
      0x01 ,  0x00,  0x01,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x51 ,  0x80,  0x80,  0x01,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1 function 1
    //
      0x01 ,  0x00,  0x01,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    IGD bus0 function 0
    //
      0x00 ,  0x02,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x42 ,  0x81,  0x00,  0x00,  0x00,  0x00,  0x20,  0x00,

    //
    //Bus  ,   Dev,  Func,    USB bus0 function 0
    //
      0x00 ,  0x16,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x32 ,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    HD Audio bus0 function 0
    //
      0x00 ,  0x1B,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x00 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,

    //
    //0xFF indicates the end of the table
    //
      0xFF
 };

  //
  // These registers have to set in byte order
  //
  UINT8                 ExtReg[] = { 0x9E, 0x9D };  // SMRAM settings



  //
  // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
  // and vital to S3 resume. That's why we put save code here
  //
  PciAddress.Bus      = 0;
  PciAddress.Device   = 0;
  PciAddress.Function = 0;
  PciAddress.ExtendedRegister = 0;

  for (Index = 0; Index < 2; Index++) {
    //
    // Read SRAM setting from Pci(0, 0, 0)
    //
    PciAddress.Register = ExtReg[Index];
    Data8 = MmioRead8 (
              MmPciAddress (0,
                PciAddress.Bus,
                PciAddress.Device,
                PciAddress.Function,
                PciAddress.Register
              )
            );

    //
    // Save latest settings to runtime script table
    //
    S3BootScriptSavePciCfgWrite(
      S3BootScriptWidthUint8,
      *(UINT64*)&PciAddress,
      1,
      &Data8
      );
  }


  //
  // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
  // and vital to S3 resume. That's why we put save code here
  //
  Index = 0;
  while (RegTable[Index] != 0xFF) {

    PciAddress.Bus      = RegTable[Index++];
    PciAddress.Device   = RegTable[Index++];
    PciAddress.Function = RegTable[Index++];
    PciAddress.Register = 0;
    PciAddress.ExtendedRegister = 0;

    Data16 = MmioRead16 (
              MmPciAddress (0,
                PciAddress.Bus,
                PciAddress.Device,
                PciAddress.Function,
                PciAddress.Register
              )
            );

    if (Data16 == 0xFFFF) {
      Index+=8;
      continue;
    }

    for (Offset = 0, Mask = 0x01; Offset < 256; Offset+=4, Mask<<=1) {

      if (Mask == 0x00) {
        Mask = 0x01;
      }

      if (RegTable[Index + Offset/32] & Mask ) {

        PciAddress.Register = (UINT8)Offset;
        Data32 = MmioRead32 (MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));

        //
        // Save latest settings to runtime script table
        //
        S3BootScriptSavePciCfgWrite (
          S3BootScriptWidthUint32,
          *(UINT64*)&PciAddress,
          1,
          &Data32
        );
      }
    }

    Index += 8;

  }


  //
  // Save I/O ports to S3 script table
  //

  //
  // Selftest KBC
  //
  Data8 = 0xAA;
  S3BootScriptSaveIoWrite (
    S3BootScriptWidthUint8,
    0x64,
    (UINTN)1,
    &Data8
    );

  Data32 = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN);

  S3BootScriptSaveIoWrite (
      S3BootScriptWidthUint32,
      (mAcpiBaseAddr + R_PCH_SMI_EN),
      1,
      &Data32
      );

  //
  // Save B_ICH_TCO_CNT_LOCK so it will be done on S3 resume path.
  //
  Data16 = IoRead16(mAcpiBaseAddr + R_PCH_TCO_CNT);

  S3BootScriptSaveIoWrite (
      S3BootScriptWidthUint16,
      mAcpiBaseAddr + R_PCH_TCO_CNT,
      1,
      &Data16
      );


  return EFI_SUCCESS;
}
예제 #30
0
/**
  Perform flash write operation with progress indicator.  The start and end
  completion percentage values are passed into this function.  If the requested
  flash write operation is broken up, then completion percentage between the
  start and end values may be passed to the provided Progress function.  The
  caller of this function is required to call the Progress function for the
  start and end completion percentage values.  This allows the Progress,
  StartPercentage, and EndPercentage parameters to be ignored if the requested
  flash write operation can not be broken up

  @param[in] FirmwareType      The type of firmware.
  @param[in] FlashAddress      The address of flash device to be accessed.
  @param[in] FlashAddressType  The type of flash device address.
  @param[in] Buffer            The pointer to the data buffer.
  @param[in] Length            The length of data buffer in bytes.
  @param[in] Progress          A function used report the progress of the
                               firmware update.  This is an optional parameter
                               that may be NULL.
  @param[in] StartPercentage   The start completion percentage value that may
                               be used to report progress during the flash
                               write operation.
  @param[in] EndPercentage     The end completion percentage value that may
                               be used to report progress during the flash
                               write operation.

  @retval EFI_SUCCESS           The operation returns successfully.
  @retval EFI_WRITE_PROTECTED   The flash device is read only.
  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
**/
EFI_STATUS
EFIAPI
PerformFlashWriteWithProgress (
  IN PLATFORM_FIRMWARE_TYPE                         FirmwareType,
  IN EFI_PHYSICAL_ADDRESS                           FlashAddress,
  IN FLASH_ADDRESS_TYPE                             FlashAddressType,
  IN VOID                                           *Buffer,
  IN UINTN                                          Length,
  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress,        OPTIONAL
  IN UINTN                                          StartPercentage,
  IN UINTN                                          EndPercentage
  )
{
  EFI_STATUS            Status = EFI_SUCCESS;
  UINTN               Index;
  EFI_PHYSICAL_ADDRESS  Address;
  UINTN                 CountOfBlocks;
  EFI_TPL               OldTpl;
  BOOLEAN               FlashError;
  UINT8                 *Buf;
  UINTN                 LpcBaseAddress;
  UINT8                 Data8Or;
  UINT8                 Data8And;
  UINT8                 BiosCntl;

  Index             = 0;
  Address           = 0;
  CountOfBlocks     = 0;
  FlashError        = FALSE;
  Buf               = Buffer;

  DEBUG((DEBUG_INFO | DEBUG_ERROR, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
  if (FlashAddressType == FlashAddressTypeRelativeAddress) {
    FlashAddress = FlashAddress + mInternalFdAddress;
  }

  CountOfBlocks = (UINTN) (Length / BLOCK_SIZE);
  Address = FlashAddress;

  LpcBaseAddress = MmPciAddress (0,
                    DEFAULT_PCI_BUS_NUMBER_PCH,
                    PCI_DEVICE_NUMBER_PCH_LPC,
                    PCI_FUNCTION_NUMBER_PCH_LPC,
                    0
                    );
  BiosCntl = MmioRead8 (LpcBaseAddress + R_PCH_LPC_BIOS_CNTL);
  if ((BiosCntl & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) {
    ///
    /// Clear SMM_BWP bit (D31:F0:RegDCh[5])
    ///
    Data8And  = (UINT8) ~B_PCH_LPC_BIOS_CNTL_SMM_BWP;
    Data8Or   = 0x00;

    MmioAndThenOr8 (
      LpcBaseAddress + R_PCH_LPC_BIOS_CNTL,
      Data8And,
      Data8Or
      );
    DEBUG((DEBUG_INFO, "PerformFlashWrite Clear SMM_BWP bit\n"));
  }

    //
    // Raise TPL to TPL_NOTIFY to block any event handler,
    // while still allowing RaiseTPL(TPL_NOTIFY) within
    // output driver during Print()
    //
    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    for (Index = 0; Index < CountOfBlocks; Index++) {
      if (Progress != NULL) {
        Progress (StartPercentage + ((Index * (EndPercentage - StartPercentage)) / CountOfBlocks));
      }
      //
      // Handle block based on address and contents.
      //
      if (!EFI_ERROR (InternalCompareBlock (Address, Buf))) {
        DEBUG((DEBUG_INFO, "Skipping block at 0x%lx (already programmed)\n", Address));
      } else {
        //
        // Make updating process uninterruptable,
        // so that the flash memory area is not accessed by other entities
        // which may interfere with the updating process
        //
        Status  = InternalEraseBlock (Address);
        if (EFI_ERROR(Status)) {
          gBS->RestoreTPL (OldTpl);
          FlashError = TRUE;
          goto Done;
        }
        Status = InternalWriteBlock (
                  Address,
                  Buf,
                  (UINT32)(Length > BLOCK_SIZE ? BLOCK_SIZE : Length)
                  );
        if (EFI_ERROR(Status)) {
          gBS->RestoreTPL (OldTpl);
          FlashError = TRUE;
          goto Done;
        }
      }

      //
      // Move to next block to update.
      //
      Address += BLOCK_SIZE;
      Buf += BLOCK_SIZE;
      if (Length > BLOCK_SIZE) {
        Length -= BLOCK_SIZE;
      } else {
        Length = 0;
      }
    }
    gBS->RestoreTPL (OldTpl);

Done:
  if ((BiosCntl & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) {
    //
    // Restore original control setting
    //
    MmioWrite8 (LpcBaseAddress + R_PCH_LPC_BIOS_CNTL, BiosCntl);
  }

  if (Progress != NULL) {
    Progress (EndPercentage);
  }

  return EFI_SUCCESS;
}