/** 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; }
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; }
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; }
/** 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; }
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 ); } }
/** 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; }
/** 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-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); }
STATIC UINTN EFIAPI PL061GetPins ( IN UINTN Address, IN UINTN Mask ) { return MmioRead8 (PL061EffectiveAddress (Address, Mask)); }
/** 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); }
/** 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; }
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); }
/** 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; }
/** 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; } }
/** 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); }
/** 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; } }
/** 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; }
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); }
/** 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; }
/** 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; }
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; }
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; }
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; }
/** 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; }
/** 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; }
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; }
/** 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; }
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; }
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; }
/** 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; }