summaryrefslogtreecommitdiff
path: root/Platform/Intel/PurleyOpenBoardPkg/Features/Ipmi/Library/IpmiLibKcs/KcsBmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/Intel/PurleyOpenBoardPkg/Features/Ipmi/Library/IpmiLibKcs/KcsBmc.c')
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Features/Ipmi/Library/IpmiLibKcs/KcsBmc.c491
1 files changed, 491 insertions, 0 deletions
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Features/Ipmi/Library/IpmiLibKcs/KcsBmc.c b/Platform/Intel/PurleyOpenBoardPkg/Features/Ipmi/Library/IpmiLibKcs/KcsBmc.c
new file mode 100644
index 0000000000..4f766517ec
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Features/Ipmi/Library/IpmiLibKcs/KcsBmc.c
@@ -0,0 +1,491 @@
+/** @file
+ KCS Transport Hook.
+
+Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "KcsBmc.h"
+#include <Library/DebugLib.h>
+
+EFI_STATUS
+KcsErrorExit (
+ UINT64 KcsTimeoutPeriod,
+ UINT16 KcsPort
+ )
+/*++
+
+Routine Description:
+
+ Check the KCS error status
+
+Arguments:
+
+ KcsPort - The base port of KCS
+
+Returns:
+
+ EFI_DEVICE_ERROR - The device error happened
+ EFI_SUCCESS - Successfully check the KCS error status
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 KcsData;
+ EFI_KCS_STATUS KcsStatus;
+ UINT8 BmcStatus;
+ UINT8 RetryCount;
+ UINT64 TimeOut;
+
+ TimeOut = 0;
+ RetryCount = 0;
+ while (RetryCount < KCS_ABORT_RETRY_COUNT) {
+
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsPort + 1);
+ if (KcsStatus.RawData == 0xFF || (TimeOut >= KcsTimeoutPeriod)) {
+ RetryCount = KCS_ABORT_RETRY_COUNT;
+ break;
+ }
+ TimeOut++;
+ } while (KcsStatus.Status.Ibf);
+
+ if (RetryCount >= KCS_ABORT_RETRY_COUNT) {
+ break;
+ }
+
+ KcsData = KCS_ABORT;
+ IoWrite8 ((KcsPort + 1), KcsData);
+
+ TimeOut = 0;
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsPort + 1);
+ if (KcsStatus.RawData == 0xFF || (TimeOut >= KcsTimeoutPeriod)) {
+ Status = EFI_DEVICE_ERROR;
+ goto LabelError;
+ }
+ TimeOut++;
+ } while (KcsStatus.Status.Ibf);
+
+ KcsData = IoRead8 (KcsPort);
+
+ KcsData = 0x0;
+ IoWrite8 (KcsPort, KcsData);
+
+ TimeOut = 0;
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsPort + 1);
+ if (KcsStatus.RawData == 0xFF || (TimeOut >= KcsTimeoutPeriod)) {
+ Status = EFI_DEVICE_ERROR;
+ goto LabelError;
+ }
+ TimeOut++;
+ } while (KcsStatus.Status.Ibf);
+
+ if (KcsStatus.Status.State == KcsReadState) {
+ TimeOut = 0;
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsPort + 1);
+ if (KcsStatus.RawData == 0xFF || (TimeOut >= KcsTimeoutPeriod)) {
+ Status = EFI_DEVICE_ERROR;
+ goto LabelError;
+ }
+ TimeOut++;
+ } while (!KcsStatus.Status.Obf);
+
+ BmcStatus = IoRead8 (KcsPort);
+
+ KcsData = KCS_READ;
+ IoWrite8 (KcsPort, KcsData);
+
+ TimeOut = 0;
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsPort + 1);
+ if (KcsStatus.RawData == 0xFF || (TimeOut >= KcsTimeoutPeriod)) {
+ Status = EFI_DEVICE_ERROR;
+ goto LabelError;
+ }
+ TimeOut++;
+ } while (KcsStatus.Status.Ibf);
+
+ if (KcsStatus.Status.State == KcsIdleState) {
+ TimeOut = 0;
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsPort + 1);
+ if (KcsStatus.RawData == 0xFF || (TimeOut >= KcsTimeoutPeriod)) {
+ Status = EFI_DEVICE_ERROR;
+ goto LabelError;
+ }
+ TimeOut++;
+ } while (!KcsStatus.Status.Obf);
+
+ KcsData = IoRead8 (KcsPort);
+ break;
+
+ } else {
+ RetryCount++;
+ continue;
+ }
+
+ } else {
+ RetryCount++;
+ continue;
+ }
+ }
+
+ if (RetryCount >= KCS_ABORT_RETRY_COUNT) {
+ Status = EFI_DEVICE_ERROR;
+ goto LabelError;
+ }
+
+ return EFI_SUCCESS;
+
+LabelError:
+
+ return Status;
+}
+
+EFI_STATUS
+KcsCheckStatus (
+ UINT64 KcsTimeoutPeriod,
+ UINT16 KcsPort,
+ KCS_STATE KcsState,
+ BOOLEAN *Idle
+ )
+/*++
+
+Routine Description:
+
+ Ckeck KCS status
+
+Arguments:
+
+ KcsPort - The base port of KCS
+ KcsState - The state of KCS to be checked
+ Idle - If the KCS is idle
+
+Returns:
+
+ EFI_SUCCESS - Checked the KCS status successfully
+
+--*/
+{
+ EFI_STATUS Status = 0;
+ EFI_KCS_STATUS KcsStatus = { 0 };
+ UINT8 KcsData = 0;
+ UINT64 TimeOut = 0;
+
+ if(Idle == NULL ){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Idle = FALSE;
+
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsPort + 1);
+ if (KcsStatus.RawData == 0xFF || (TimeOut >= KcsTimeoutPeriod)) {
+ Status = EFI_DEVICE_ERROR;
+ goto LabelError;
+ }
+ TimeOut++;
+ } while (KcsStatus.Status.Ibf);
+
+ if (KcsState == KcsWriteState) {
+ KcsData = IoRead8 (KcsPort);
+ }
+
+ if (KcsStatus.Status.State != KcsState) {
+ if ((KcsStatus.Status.State == KcsIdleState) && (KcsState == KcsReadState)) {
+ *Idle = TRUE;
+ } else {
+ Status = KcsErrorExit (KcsTimeoutPeriod, KcsPort);
+ goto LabelError;
+ }
+ }
+
+ if (KcsState == KcsReadState) {
+ TimeOut = 0;
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsPort + 1);
+ if (KcsStatus.RawData == 0xFF || (TimeOut >= KcsTimeoutPeriod)) {
+ Status = EFI_DEVICE_ERROR;
+ goto LabelError;
+ }
+ TimeOut++;
+ } while (!KcsStatus.Status.Obf);
+ }
+
+ if (KcsState == KcsWriteState || Idle) {
+ KcsData = IoRead8 (KcsPort);
+ }
+
+ return EFI_SUCCESS;
+
+LabelError:
+
+ return Status;
+}
+
+EFI_STATUS
+SendDataToBmc (
+ UINT64 KcsTimeoutPeriod,
+ UINT16 KcsPort,
+ UINT8 *Data,
+ UINT8 DataSize
+ )
+/*++
+
+Routine Description:
+
+ Send data to BMC
+
+Arguments:
+
+ Data - The data pointer to be sent
+ DataSize - The data size
+
+Returns:
+
+ EFI_SUCCESS - Send out the data successfully
+
+--*/
+{
+ EFI_KCS_STATUS KcsStatus;
+ UINT8 KcsData;
+ UINT16 KcsIoBase;
+ EFI_STATUS Status;
+ UINT8 i;
+ BOOLEAN Idle;
+ UINT64 TimeOut = 0;
+
+ DEBUG ((DEBUG_INFO, "SendDataToBmc (%ld, 0x%x) - ", KcsTimeoutPeriod, KcsPort));
+ for (i = 0; i < DataSize; i++) {
+ DEBUG ((DEBUG_INFO, "%02x ", Data[i]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ KcsIoBase = KcsPort;
+
+ do {
+ MicroSecondDelay(KCS_DELAY_UNIT);
+ KcsStatus.RawData = IoRead8 (KcsIoBase + 1);
+ if ((KcsStatus.RawData == 0xFF) || (TimeOut >= KcsTimeoutPeriod))
+ {
+ if ((Status = KcsErrorExit (KcsTimeoutPeriod, KcsIoBase)) != EFI_SUCCESS)
+ {
+ DEBUG ((DEBUG_INFO, "KcsErrorExit - %r\n", Status));
+ return Status;
+ }
+ }
+ TimeOut++;
+ } while (KcsStatus.Status.Ibf);
+
+ KcsData = KCS_WRITE_START;
+ IoWrite8 ((KcsIoBase + 1), KcsData);
+ if ((Status = KcsCheckStatus (KcsTimeoutPeriod, KcsIoBase, KcsWriteState, &Idle)) != EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "KcsCheckStatus 1 - %r\n", Status));
+ return Status;
+ }
+
+ for (i = 0; i < DataSize; i++) {
+ if (i == (DataSize - 1)) {
+ if ((Status = KcsCheckStatus (KcsTimeoutPeriod, KcsIoBase, KcsWriteState, &Idle)) != EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "KcsCheckStatus 2 - %r\n", Status));
+ return Status;
+ }
+
+ KcsData = KCS_WRITE_END;
+ IoWrite8 ((KcsIoBase + 1), KcsData);
+ }
+
+ Status = KcsCheckStatus (KcsTimeoutPeriod, KcsIoBase, KcsWriteState, &Idle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "KcsCheckStatus 3 - %r\n", Status));
+ return Status;
+ }
+
+ IoWrite8 (KcsIoBase, Data[i]);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReceiveBmcData (
+ UINT64 KcsTimeoutPeriod,
+ UINT16 KcsPort,
+ UINT8 *Data,
+ UINT8 *DataSize
+ )
+/*++
+
+Routine Description:
+
+ Routine Description:
+
+ Receive data from BMC
+
+Arguments:
+
+ Data - The buffer pointer
+ DataSize - The buffer size
+
+Returns:
+
+ EFI_SUCCESS - Received data successfully
+
+--*/
+{
+ UINT8 KcsData;
+ UINT16 KcsIoBase;
+ EFI_STATUS Status;
+ BOOLEAN Idle;
+ UINT8 Count;
+
+ Count = 0;
+ KcsIoBase = KcsPort;
+
+ DEBUG ((DEBUG_INFO, "ReceiveBmcData (%ld, 0x%x)...\n", KcsTimeoutPeriod, KcsPort));
+
+ while (TRUE) {
+
+ if ((Status = KcsCheckStatus (KcsTimeoutPeriod, KcsIoBase, KcsReadState, &Idle)) != EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "KcsCheckStatus - %r\n", Status));
+ return Status;
+ }
+
+ if (Idle) {
+ DEBUG ((DEBUG_INFO, "DataSize - 0x%x\n", Count));
+ *DataSize = Count;
+ break;
+ }
+
+ if (Count > *DataSize) {
+ DEBUG ((DEBUG_INFO, "ERROR: Count(0x%x) > *DataSize(0x%x)\n", Count, *DataSize));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Data[Count] = IoRead8 (KcsIoBase);
+
+ Count++;
+
+ KcsData = KCS_READ;
+ IoWrite8 (KcsIoBase, KcsData);
+ }
+
+ DEBUG ((DEBUG_INFO, "ReceiveBmcData (%ld, 0x%x) - ", KcsTimeoutPeriod, KcsPort));
+ for (Count = 0; Count < *DataSize; Count++) {
+ DEBUG ((DEBUG_INFO, "%02x ", Data[Count]));
+ }
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReceiveBmcDataFromPort (
+ UINT64 KcsTimeoutPeriod,
+ UINT16 KcsPort,
+ UINT8 *Data,
+ UINT8 *DataSize
+ )
+/*++
+
+Routine Description:
+
+ Receive data from BMC
+
+Arguments:
+
+ Data - The buffer pointer to receive data
+ DataSize - The buffer size
+
+Returns:
+
+ EFI_SUCCESS - Received the data successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 KcsIoBase;
+ UINT8 i;
+ UINT8 MyDataSize;
+
+ MyDataSize = *DataSize;
+
+ KcsIoBase = KcsPort;
+
+ for (i = 0; i < KCS_ABORT_RETRY_COUNT; i++) {
+ Status = ReceiveBmcData (KcsTimeoutPeriod, KcsIoBase, Data, DataSize);
+ if (EFI_ERROR (Status)) {
+ if ((Status = KcsErrorExit (KcsTimeoutPeriod, KcsIoBase)) != EFI_SUCCESS) {
+ return Status;
+ }
+
+ *DataSize = MyDataSize;
+ } else {
+ return Status;
+ }
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+EFI_STATUS
+SendDataToBmcPort (
+ UINT64 KcsTimeoutPeriod,
+ UINT16 KcsPort,
+ UINT8 *Data,
+ UINT8 DataSize
+ )
+/*++
+
+Routine Description:
+
+ Send data to BMC
+
+Arguments:
+
+ Data - The data pointer to be sent
+ DataSize - The data size
+
+Returns:
+
+ EFI_SUCCESS - Send out the data successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 KcsIoBase;
+ UINT8 i;
+
+ KcsIoBase = KcsPort;
+
+ for (i = 0; i < KCS_ABORT_RETRY_COUNT; i++) {
+ Status = SendDataToBmc (KcsTimeoutPeriod, KcsIoBase, Data, DataSize);
+ if (EFI_ERROR (Status)) {
+ if ((Status = KcsErrorExit (KcsTimeoutPeriod, KcsIoBase)) != EFI_SUCCESS) {
+ return Status;
+ }
+ } else {
+ return Status;
+ }
+ }
+
+ return EFI_DEVICE_ERROR;
+}