+/**\r
+ This function check if the address is in SMRAM.\r
+\r
+ @param Buffer the buffer address to be checked.\r
+ @param Length the buffer length to be checked.\r
+\r
+ @retval TRUE this address is in SMRAM.\r
+ @retval FALSE this address is NOT in SMRAM.\r
+**/\r
+BOOLEAN\r
+InternalIsAddressInSmram (\r
+ IN EFI_PHYSICAL_ADDRESS Buffer,\r
+ IN UINT64 Length\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
+ if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||\r
+ ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ This function check if the address refered by Buffer and Length is valid.\r
+\r
+ @param Buffer the buffer address to be checked.\r
+ @param Length the buffer length to be checked.\r
+\r
+ @retval TRUE this address is valid.\r
+ @retval FALSE this address is NOT valid.\r
+**/\r
+BOOLEAN\r
+InternalIsAddressValid (\r
+ IN UINTN Buffer,\r
+ IN UINTN Length\r
+ )\r
+{\r
+ if (Buffer > (MAX_ADDRESS - Length)) {\r
+ //\r
+ // Overflow happen\r
+ //\r
+ return FALSE;\r
+ }\r
+ if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)Buffer, (UINT64)Length)) {\r
+ return FALSE;\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Communication service SMI Handler entry.\r
+\r
+ This SMI handler provides services for report SMM boot records. \r
+\r
+ Caution: This function may receive untrusted input.\r
+ Communicate buffer and buffer size are external input, so this function will do basic validation.\r
+\r
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
+ @param[in] RegisterContext Points to an optional handler context which was specified when the\r
+ handler was registered.\r
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will\r
+ be conveyed from a non-SMM environment into an SMM environment.\r
+ @param[in, out] CommBufferSize The size of the CommBuffer.\r
+\r
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers \r
+ should still be called.\r
+ @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should \r
+ still be called.\r
+ @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still \r
+ be called.\r
+ @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FpdtSmiHandler (\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *RegisterContext,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;\r
+ UINTN BootRecordSize;\r
+ VOID *BootRecordData;\r
+\r
+ //\r
+ // If input is invalid, stop processing this SMI\r
+ //\r
+ if (CommBuffer == NULL || CommBufferSize == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if(*CommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ if (!InternalIsAddressValid ((UINTN)CommBuffer, *CommBufferSize)) {\r
+ DEBUG ((EFI_D_ERROR, "FpdtSmiHandler: SMM communication data buffer in SMRAM or overflow!\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)CommBuffer;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ switch (SmmCommData->Function) {\r
+ case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE :\r
+ SmmCommData->BootRecordSize = mBootRecordSize;\r
+ break;\r
+\r
+ case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA :\r
+ BootRecordData = SmmCommData->BootRecordData;\r
+ BootRecordSize = SmmCommData->BootRecordSize;\r
+ if (BootRecordData == NULL || BootRecordSize < mBootRecordSize) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ } \r
+\r
+ //\r
+ // Sanity check\r
+ //\r
+ SmmCommData->BootRecordSize = mBootRecordSize;\r
+ if (!InternalIsAddressValid ((UINTN)BootRecordData, mBootRecordSize)) {\r
+ DEBUG ((EFI_D_ERROR, "FpdtSmiHandler: SMM Data buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ break;\r
+ }\r
+\r
+ CopyMem (\r
+ (UINT8*)BootRecordData, \r
+ mBootRecordBuffer, \r
+ mBootRecordSize\r
+ );\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SmmCommData->ReturnStatus = Status;\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r