+\r
+Done:\r
+ //\r
+ // On output, actual profile data size copied.\r
+ //\r
+ *ProfileSize -= RemainingSize;\r
+ //\r
+ // On output, next time profile buffer offset to copy.\r
+ //\r
+ *ProfileOffset = Offset;\r
+}\r
+\r
+/**\r
+ Get memory profile data.\r
+\r
+ @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.\r
+ @param[in, out] ProfileSize On entry, points to the size in bytes of the ProfileBuffer.\r
+ On return, points to the size of the data returned in ProfileBuffer.\r
+ @param[out] ProfileBuffer Profile buffer.\r
+\r
+ @return EFI_SUCCESS Get the memory profile data successfully.\r
+ @return EFI_UNSUPPORTED Memory profile is unsupported.\r
+ @return EFI_BUFFER_TO_SMALL The ProfileSize is too small for the resulting data.\r
+ ProfileSize is updated with the size required.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmramProfileProtocolGetData (\r
+ IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,\r
+ IN OUT UINT64 *ProfileSize,\r
+ OUT VOID *ProfileBuffer\r
+ )\r
+{\r
+ UINT64 Size;\r
+ UINT64 Offset;\r
+ MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
+ BOOLEAN SmramProfileGettingStatus;\r
+\r
+ ContextData = GetSmramProfileContext ();\r
+ if (ContextData == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ SmramProfileGettingStatus = mSmramProfileGettingStatus;\r
+ mSmramProfileGettingStatus = TRUE;\r
+\r
+ Size = SmramProfileGetDataSize ();\r
+\r
+ if (*ProfileSize < Size) {\r
+ *ProfileSize = Size;\r
+ mSmramProfileGettingStatus = SmramProfileGettingStatus;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ Offset = 0;\r
+ SmramProfileCopyData (ProfileBuffer, &Size, &Offset);\r
+ *ProfileSize = Size;\r
+\r
+ mSmramProfileGettingStatus = SmramProfileGettingStatus;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Register image to memory profile.\r
+\r
+ @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.\r
+ @param[in] FilePath File path of the image.\r
+ @param[in] ImageBase Image base address.\r
+ @param[in] ImageSize Image size.\r
+ @param[in] FileType File type of the image.\r
+\r
+ @return EFI_SUCCESS Register successfully.\r
+ @return EFI_UNSUPPORTED Memory profile is unsupported,\r
+ or memory profile for the image is not required.\r
+ @return EFI_OUT_OF_RESOURCES No enough resource for this register.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmramProfileProtocolRegisterImage (\r
+ IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN PHYSICAL_ADDRESS ImageBase,\r
+ IN UINT64 ImageSize,\r
+ IN EFI_FV_FILETYPE FileType\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SMM_DRIVER_ENTRY DriverEntry;\r
+ VOID *EntryPointInImage;\r
+ EFI_GUID *Name;\r
+\r
+ ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
+ Name = GetFileNameFromFilePath (FilePath);\r
+ if (Name != NULL) {\r
+ CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));\r
+ }\r
+ DriverEntry.ImageBuffer = ImageBase;\r
+ DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize);\r
+ Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
+ ASSERT_EFI_ERROR (Status);\r
+ DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
+\r
+ return RegisterSmramProfileImage (&DriverEntry, FALSE);\r
+}\r
+\r
+/**\r
+ Unregister image from memory profile.\r
+\r
+ @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.\r
+ @param[in] FilePath File path of the image.\r
+ @param[in] ImageBase Image base address.\r
+ @param[in] ImageSize Image size.\r
+\r
+ @return EFI_SUCCESS Unregister successfully.\r
+ @return EFI_UNSUPPORTED Memory profile is unsupported,\r
+ or memory profile for the image is not required.\r
+ @return EFI_NOT_FOUND The image is not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmramProfileProtocolUnregisterImage (\r
+ IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN PHYSICAL_ADDRESS ImageBase,\r
+ IN UINT64 ImageSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SMM_DRIVER_ENTRY DriverEntry;\r
+ VOID *EntryPointInImage;\r
+ EFI_GUID *Name;\r
+\r
+ ZeroMem (&DriverEntry, sizeof (DriverEntry));\r
+ Name = GetFileNameFromFilePath (FilePath);\r
+ if (Name != NULL) {\r
+ CopyMem (&DriverEntry.FileName, Name, sizeof (EFI_GUID));\r
+ }\r
+ DriverEntry.ImageBuffer = ImageBase;\r
+ DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN) ImageSize);\r
+ Status = InternalPeCoffGetEntryPoint ((VOID *) (UINTN) DriverEntry.ImageBuffer, &EntryPointInImage);\r
+ ASSERT_EFI_ERROR (Status);\r
+ DriverEntry.ImageEntryPoint = (PHYSICAL_ADDRESS) (UINTN) EntryPointInImage;\r
+\r
+ return UnregisterSmramProfileImage (&DriverEntry, FALSE);\r
+}\r
+\r
+/**\r
+ Get memory profile recording state.\r
+\r
+ @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.\r
+ @param[out] RecordingState Recording state.\r
+\r
+ @return EFI_SUCCESS Memory profile recording state is returned.\r
+ @return EFI_UNSUPPORTED Memory profile is unsupported.\r
+ @return EFI_INVALID_PARAMETER RecordingState is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmramProfileProtocolGetRecordingState (\r
+ IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,\r
+ OUT BOOLEAN *RecordingState\r
+ )\r
+{\r
+ MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
+\r
+ ContextData = GetSmramProfileContext ();\r
+ if (ContextData == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (RecordingState == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ *RecordingState = mSmramProfileRecordingEnable;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Set memory profile recording state.\r
+\r
+ @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.\r
+ @param[in] RecordingState Recording state.\r
+\r
+ @return EFI_SUCCESS Set memory profile recording state successfully.\r
+ @return EFI_UNSUPPORTED Memory profile is unsupported.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmramProfileProtocolSetRecordingState (\r
+ IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,\r
+ IN BOOLEAN RecordingState\r
+ )\r
+{\r
+ MEMORY_PROFILE_CONTEXT_DATA *ContextData;\r
+\r
+ ContextData = GetSmramProfileContext ();\r
+ if (ContextData == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ mSmramProfileRecordingEnable = RecordingState;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Record memory profile of multilevel caller.\r
+\r
+ @param[in] This The EDKII_SMM_MEMORY_PROFILE_PROTOCOL instance.\r
+ @param[in] CallerAddress Address of caller.\r
+ @param[in] Action Memory profile action.\r
+ @param[in] MemoryType Memory type.\r
+ EfiMaxMemoryType means the MemoryType is unknown.\r
+ @param[in] Buffer Buffer address.\r
+ @param[in] Size Buffer size.\r
+ @param[in] ActionString String for memory profile action.\r
+ Only needed for user defined allocate action.\r
+\r
+ @return EFI_SUCCESS Memory profile is updated.\r
+ @return EFI_UNSUPPORTED Memory profile is unsupported,\r
+ or memory profile for the image is not required,\r
+ or memory profile for the memory type is not required.\r
+ @return EFI_ACCESS_DENIED It is during memory profile data getting.\r
+ @return EFI_ABORTED Memory profile recording is not enabled.\r
+ @return EFI_OUT_OF_RESOURCES No enough resource to update memory profile for allocate action.\r
+ @return EFI_NOT_FOUND No matched allocate info found for free action.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmramProfileProtocolRecord (\r
+ IN EDKII_SMM_MEMORY_PROFILE_PROTOCOL *This,\r
+ IN PHYSICAL_ADDRESS CallerAddress,\r
+ IN MEMORY_PROFILE_ACTION Action,\r
+ IN EFI_MEMORY_TYPE MemoryType,\r
+ IN VOID *Buffer,\r
+ IN UINTN Size,\r
+ IN CHAR8 *ActionString OPTIONAL\r
+ )\r
+{\r
+ return SmmCoreUpdateProfile (CallerAddress, Action, MemoryType, Size, Buffer, ActionString);\r