summaryrefslogtreecommitdiff
path: root/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c')
-rw-r--r--Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c487
1 files changed, 487 insertions, 0 deletions
diff --git a/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c b/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c
new file mode 100644
index 0000000..e5ec2d2
--- /dev/null
+++ b/Core/EM/usb/AmiUsbLib/AmiUsbSmmGlobalDataValidationLib.c
@@ -0,0 +1,487 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: AmiUsbSmmGlobalDataValidationLib.c
+//
+// Description: Source code for the AmiUsbSmmGlobalDataValidationLib library class.
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Token.h>
+#include <AmiDxeLib.h>
+#include <AmiBufferValidationLib.h>
+#include <AmiUsbSmmGlobalDataValidationLib.h>
+#include <Protocol/SmmAccess2.h>
+#include <Protocol/SmmBase2.h>
+#include "../rt/UsbDef.h"
+#include "../rt/Xhci.h"
+
+extern UINT32 mCrcTable[256];
+extern EFI_STATUS EFIAPI RuntimeDriverCalculateCrc32(VOID *, UINTN, UINT32*);
+extern VOID RuntimeDriverInitializeCrc32Table(VOID);
+
+AMI_USB_SMM_PROTOCOL *gAmiUsbSmmProtocol = NULL;
+EFI_SMM_SYSTEM_TABLE2 *gSmst2 = NULL;
+
+typedef struct {
+ UINT32 UsbLegSupOffSet;
+ XHCI_DCBAA *DcbaaPtr;
+ TRB_RING *XfrRings;
+ UINTN XfrTrbs;
+ VOID *DeviceContext;
+ VOID *InputContext;
+ UINT64 *ScratchBufEntry;
+ UINT8 ContextSize;
+ UINT32 HashValue;
+} USB3_HC_CONSTANT_DATA;
+
+typedef struct {
+ UINT8 HcType;
+ UINT8 OpRegOffset;
+ UINT8 ExtCapPtr;
+ UINT16 BusDevFuncNum;
+ UINT16 AsyncListSize;
+ UINT32 *FrameList;
+ UINTN BaseAddressSize;
+ VOID *UsbBusData;
+ VOID *IsocTds;
+ UINT32 HashValue;
+} USB_HC_CONSTANT_DATA;
+
+typedef struct {
+ HCD_HEADER HcdriverTable[MAX_HC_TYPES];
+ DEV_DRIVER DevDriverTable[MAX_DEVICE_TYPES];
+ DEV_DRIVER DelayedDrivers[MAX_DEVICE_TYPES];
+ CALLBACK_FUNC CallBackFunctionTable[MAX_CALLBACK_FUNCTION];
+ VOID *EfiKeyboardBuffer;
+ UINT8 *MemBlockStart;
+ UINT32 MemPages;
+ UINT8 *UsbTempBuffer;
+ UINT8 *UsbMassConsumeBuffer;
+ UINT32 *MemBlkSts;
+ UINTN PciExpressBaseAddress;
+ VOID *QueueCnnctDiscData;
+ int QueueCnnctDiscMaxSize;
+ VOID *IccQueueCnnctDiscData;
+ int IccQueueCnnctDiscMaxSize;
+ UINT32 HashValue;
+} USB_CONSTANT_DATA;
+
+EFI_STATUS
+CalculateUsbGlobalConstantDataCrc32(
+ USB_GLOBAL_DATA *UsbData,
+ UINT32 *Crc32
+)
+{
+ USB_CONSTANT_DATA UsbConStantData = {0};
+ UINTN Index = 0;
+ HC_STRUC *HcStruc;
+ USB3_HOST_CONTROLLER *Usb3Hc = NULL;
+ UINTN HcInitializedNumber = 0;
+ UINTN Usb3HcInitializedNumber = 0;
+ UINTN HcStrucDataIndex = 0;
+ UINTN Usb3HcStrucDataIndex = 0;
+ USB_HC_CONSTANT_DATA *HcStrucData = NULL;
+ USB3_HC_CONSTANT_DATA *Usb3HcStrucData = NULL;
+ EFI_STATUS Status;
+ UINT32 Crc32Value[3] = {0};
+
+ if (gAmiUsbSmmProtocol == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ MemCpy(UsbConStantData.HcdriverTable, UsbData->aHCDriverTable, sizeof(UsbConStantData.HcdriverTable));
+ MemCpy(UsbConStantData.DevDriverTable, UsbData->aDevDriverTable, sizeof(UsbConStantData.DevDriverTable));
+ MemCpy(UsbConStantData.DelayedDrivers, UsbData->aDelayedDrivers, sizeof(UsbConStantData.DelayedDrivers));
+ MemCpy(UsbConStantData.CallBackFunctionTable, UsbData->aCallBackFunctionTable, sizeof(UsbConStantData.CallBackFunctionTable));
+
+ UsbConStantData.EfiKeyboardBuffer = UsbData->EfiKeyboardBuffer;
+ UsbConStantData.UsbTempBuffer = UsbData->fpUSBTempBuffer;
+ UsbConStantData.UsbMassConsumeBuffer = UsbData->fpUSBMassConsumeBuffer;
+ UsbConStantData.MemBlkSts = UsbData->aMemBlkSts;
+ UsbConStantData.MemBlockStart = UsbData->fpMemBlockStart;
+ UsbConStantData.MemPages = UsbData->MemPages;
+ UsbConStantData.QueueCnnctDiscData = UsbData->QueueCnnctDisc.data;
+ UsbConStantData.QueueCnnctDiscMaxSize = UsbData->QueueCnnctDisc.maxsize;
+ UsbConStantData.IccQueueCnnctDiscData = UsbData->ICCQueueCnnctDisc.data;
+ UsbConStantData.IccQueueCnnctDiscMaxSize = UsbData->ICCQueueCnnctDisc.maxsize;
+ UsbConStantData.HashValue = gAmiUsbSmmProtocol->GlobalDataValidation.Crc32Hash;
+
+ for (Index = 0; Index < UsbData->HcTableCount; Index++) {
+ HcStruc = UsbData->HcTable[Index];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ if (HcStruc->dHCFlag & (HC_STATE_RUNNING |HC_STATE_INITIALIZED)) {
+ HcInitializedNumber++;
+ if (HcStruc->usbbus_data) {
+ Usb3HcInitializedNumber++;
+ }
+ }
+ }
+
+ if (HcInitializedNumber != 0) {
+ Status = gSmst2->SmmAllocatePool(EfiRuntimeServicesData,
+ sizeof(USB_HC_CONSTANT_DATA) * HcInitializedNumber,
+ (VOID**)&HcStrucData);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ MemSet(HcStrucData, sizeof(USB_HC_CONSTANT_DATA) * HcInitializedNumber, 0);
+ }
+
+ if (Usb3HcInitializedNumber != 0) {
+
+ Status = gSmst2->SmmAllocatePool(EfiRuntimeServicesData,
+ sizeof(USB3_HC_CONSTANT_DATA) * Usb3HcInitializedNumber,
+ (VOID**)&Usb3HcStrucData);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ MemSet(Usb3HcStrucData, sizeof(USB3_HC_CONSTANT_DATA) * Usb3HcInitializedNumber, 0);
+ }
+
+ for (Index = 0; Index < UsbData->HcTableCount; Index++) {
+ HcStruc = UsbData->HcTable[Index];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ Status = AmiValidateMemoryBuffer((VOID*)HcStruc, sizeof(HC_STRUC));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ if (HcStruc->dHCFlag & (HC_STATE_RUNNING |HC_STATE_INITIALIZED)) {
+ HcStrucData[HcStrucDataIndex].HcType = HcStruc->bHCType;
+ HcStrucData[HcStrucDataIndex].AsyncListSize = HcStruc->wAsyncListSize;
+ HcStrucData[HcStrucDataIndex].FrameList = HcStruc->fpFrameList;
+ HcStrucData[HcStrucDataIndex].BaseAddressSize = HcStruc->BaseAddressSize;
+ HcStrucData[HcStrucDataIndex].BusDevFuncNum = HcStruc->wBusDevFuncNum;
+ HcStrucData[HcStrucDataIndex].OpRegOffset = HcStruc->bOpRegOffset;
+ HcStrucData[HcStrucDataIndex].ExtCapPtr = HcStruc->bExtCapPtr;
+ HcStrucData[HcStrucDataIndex].UsbBusData = HcStruc->usbbus_data;
+ HcStrucData[HcStrucDataIndex].HashValue = gAmiUsbSmmProtocol->GlobalDataValidation.Crc32Hash;
+ HcStrucDataIndex++;
+ if (HcStruc->usbbus_data) {
+ Usb3Hc = HcStruc->usbbus_data;
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc, sizeof(USB3_HOST_CONTROLLER));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ if (Usb3Hc->CapRegs) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->CapRegs, sizeof(XHCI_HC_CAP_REGS));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->OpRegs) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->OpRegs, sizeof(XHCI_HC_OP_REGS));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->RtRegs) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->RtRegs,
+ (sizeof(UINT32) * 8) + (sizeof(XHCI_INTERRUPTER_REGS) * Usb3Hc->CapRegs->HcsParams1.MaxIntrs));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->ExtLegCap) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->ExtLegCap, sizeof(XHCI_EXT_LEG_CAP));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->Usb2Protocol) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->Usb2Protocol, sizeof(XHCI_EXT_PROTOCOL));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->Usb3Protocol) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->Usb3Protocol, sizeof(XHCI_EXT_PROTOCOL));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ if (Usb3Hc->DbCapRegs) {
+ Status = AmiValidateMemoryBuffer((VOID*)Usb3Hc->DbCapRegs, sizeof(XHCI_DB_CAP_REGS));
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ Usb3HcStrucData[Usb3HcStrucDataIndex].DcbaaPtr = Usb3Hc->DcbaaPtr;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].XfrRings = Usb3Hc->XfrRings;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].XfrTrbs = Usb3Hc->XfrTrbs;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].DeviceContext = Usb3Hc->DeviceContext;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].InputContext = Usb3Hc->InputContext;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].ScratchBufEntry = Usb3Hc->ScratchBufEntry;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].ContextSize = Usb3Hc->ContextSize;
+ Usb3HcStrucData[Usb3HcStrucDataIndex].HashValue = gAmiUsbSmmProtocol->GlobalDataValidation.Crc32Hash;
+ Usb3HcStrucDataIndex++;
+ }
+ }
+ }
+
+ if (HcInitializedNumber != 0) {
+ Status = RuntimeDriverCalculateCrc32((UINT8*)HcStrucData,
+ (UINTN)(sizeof(USB_HC_CONSTANT_DATA) * HcInitializedNumber), &Crc32Value[0]);
+ Status = gSmst2->SmmFreePool(HcStrucData);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+
+ if (Usb3HcInitializedNumber != 0) {
+ Status = RuntimeDriverCalculateCrc32((UINT8*)Usb3HcStrucData,
+ (UINTN)(sizeof(USB3_HC_CONSTANT_DATA) * Usb3HcInitializedNumber), &Crc32Value[1]);
+ Status = gSmst2->SmmFreePool(Usb3HcStrucData);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ }
+ Status = RuntimeDriverCalculateCrc32((UINT8*)&UsbConStantData, sizeof(UsbConStantData), &Crc32Value[2]);
+
+ RuntimeDriverCalculateCrc32((UINT8*)Crc32Value, sizeof(Crc32Value), Crc32);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UpdateAmiUsbSmmGlobalDataCrc32(
+ VOID *UsbGlobdaData
+)
+{
+ EFI_STATUS Status;
+ UINT32 Crc32;
+
+
+ Status = CalculateUsbGlobalConstantDataCrc32(UsbGlobdaData, &Crc32);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ gAmiUsbSmmProtocol->GlobalDataValidation.ConstantDataCrc32 = Crc32;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CheckAmiUsbSmmGlobalDataCrc32(
+ VOID *UsbGlobdaData
+)
+{
+ EFI_STATUS Status;
+ UINT32 Crc32;
+
+ Status = CalculateUsbGlobalConstantDataCrc32(UsbGlobdaData, &Crc32);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (gAmiUsbSmmProtocol->GlobalDataValidation.ConstantDataCrc32 != Crc32) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+AmiUsbSmmGlobalDataValidation(
+ VOID *UsbGlobalData
+)
+{
+ USB_GLOBAL_DATA *UsbData;
+ EFI_STATUS Status;
+ UINT8 *MouseInputBufferEnd;
+ UINT8 *KbcharacterBufferEnd;
+ UINT8 *KbcScanCodeBufferEnd;
+ UINT8 *KbcUsbDataBufferEnd;
+ UINTN Index;
+ DEV_INFO *DevInfoTableEnd;
+ HC_STRUC *HcStruc;
+
+ UsbData = (USB_GLOBAL_DATA*)UsbGlobalData;
+
+ MouseInputBufferEnd = UsbData->aMouseInputBuffer + sizeof(UsbData->aMouseInputBuffer);
+
+ if ((UsbData->fpMouseInputBufferHeadPtr < UsbData->aMouseInputBuffer) ||
+ (UsbData->fpMouseInputBufferHeadPtr > MouseInputBufferEnd) ||
+ (UsbData->fpMouseInputBufferTailPtr < UsbData->aMouseInputBuffer) ||
+ (UsbData->fpMouseInputBufferTailPtr > MouseInputBufferEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ KbcUsbDataBufferEnd = UsbData->aKBCUsbDataBufferStart + sizeof(UsbData->aKBCUsbDataBufferStart);
+
+ if ((UsbData->aKBCUsbDataBufferHead < UsbData->aKBCUsbDataBufferStart) ||
+ (UsbData->aKBCUsbDataBufferHead > KbcUsbDataBufferEnd) ||
+ (UsbData->aKBCUsbDataBufferTail < UsbData->aKBCUsbDataBufferStart) ||
+ (UsbData->aKBCUsbDataBufferTail > KbcUsbDataBufferEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ KbcharacterBufferEnd = UsbData->aKBCCharacterBufferStart + sizeof(UsbData->aKBCCharacterBufferStart);
+
+ if ((UsbData->fpKBCCharacterBufferHead < UsbData->aKBCCharacterBufferStart) ||
+ (UsbData->fpKBCCharacterBufferHead > KbcharacterBufferEnd) ||
+ (UsbData->fpKBCCharacterBufferTail < UsbData->aKBCCharacterBufferStart) ||
+ (UsbData->fpKBCCharacterBufferTail > KbcharacterBufferEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ KbcScanCodeBufferEnd = UsbData->aKBCScanCodeBufferStart + sizeof(UsbData->aKBCScanCodeBufferStart);
+
+ if ((UsbData->fpKBCScanCodeBufferPtr < UsbData->aKBCScanCodeBufferStart) ||
+ (UsbData->fpKBCScanCodeBufferPtr > KbcScanCodeBufferEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ DevInfoTableEnd = UsbData->aDevInfoTable + sizeof(UsbData->aDevInfoTable);
+
+ if (UsbData->fpKeyRepeatDevInfo != NULL) {
+ if ((UsbData->fpKeyRepeatDevInfo < UsbData->aDevInfoTable) ||
+ (UsbData->fpKeyRepeatDevInfo > DevInfoTableEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ for (Index = 0; Index < USB_DEV_HID_COUNT; Index++) {
+ if (UsbData->aUSBKBDeviceTable[Index] != NULL) {
+ if ((UsbData->aUSBKBDeviceTable[Index] < UsbData->aDevInfoTable) ||
+ (UsbData->aUSBKBDeviceTable[Index] > DevInfoTableEnd)) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+ }
+
+ if (UsbData->HcTableCount != 0) {
+ Status = AmiValidateMemoryBuffer((VOID*)UsbData->HcTable, sizeof(HC_STRUC) * UsbData->HcTableCount);
+ if (EFI_ERROR(Status)) {
+ return EFI_ACCESS_DENIED;
+ }
+ for (Index = 0; Index < UsbData->HcTableCount; Index++) {
+ HcStruc = UsbData->HcTable[Index];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ //Check if MMIO address space of usb controller resides in SMRAM region. If yes, don't proceed.
+ if (HcStruc->bHCType != USB_HC_UHCI) {
+ if (HcStruc->BaseAddress != 0) {
+ Status = AmiValidateMmioBuffer((VOID*)HcStruc->BaseAddress, HcStruc->BaseAddressSize);
+ if (EFI_ERROR(Status)) {
+ TRACE((-1, "Usb Mmio address is invalid, it is in SMRAM\n"));
+ return EFI_ACCESS_DENIED;
+ }
+ }
+ }
+ }
+ }
+
+ Status = CheckAmiUsbSmmGlobalDataCrc32(UsbData);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UsbSmmProtocolCallback(
+ CONST EFI_GUID *Protocol,
+ VOID *Interface,
+ EFI_HANDLE Handle
+)
+{
+ EFI_STATUS Status;
+
+ Status = gSmst2->SmmLocateProtocol(
+ &gAmiUsbSmmProtocolGuid,
+ NULL,
+ &gAmiUsbSmmProtocol);
+
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+InitAmiUsbSmmGlobalDataValidationLib(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS Status;
+ VOID *ProtocolNotifyRegistration;
+ EFI_SMM_BASE2_PROTOCOL *SmmBase2;
+
+ InitAmiSmmLib(ImageHandle,SystemTable);
+
+ Status = pBS->LocateProtocol(&gEfiSmmBase2ProtocolGuid, NULL, &SmmBase2);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = SmmBase2->GetSmstLocation(SmmBase2, &gSmst2);
+
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ RuntimeDriverInitializeCrc32Table();
+
+ Status = gSmst2->SmmLocateProtocol(
+ &gAmiUsbSmmProtocolGuid,
+ NULL,
+ &gAmiUsbSmmProtocol);
+
+ if (EFI_ERROR(Status)) {
+ Status = gSmst2->SmmRegisterProtocolNotify(
+ &gAmiUsbSmmProtocolGuid,
+ UsbSmmProtocolCallback,
+ &ProtocolNotifyRegistration
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************