]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
MdeModulePkg PiSmmIpl: Handle CommSize OPTIONAL case
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / PiSmmIpl.c
index 2601275ab85fce7a6179e382b2b1252915a9f6dc..31d2c9e45e1f56e7483892ab5e246a3f3e9b03cb 100644 (file)
@@ -440,37 +440,55 @@ SmmBase2GetSmstLocation (
   after SetVirtualAddressMap().\r
 \r
   @param[in] This                The EFI_SMM_COMMUNICATION_PROTOCOL instance.\r
   after SetVirtualAddressMap().\r
 \r
   @param[in] This                The EFI_SMM_COMMUNICATION_PROTOCOL instance.\r
-  @param[in, out] CommBuffer          A pointer to the buffer to convey into SMRAM.\r
-  @param[in, out] CommSize            The size of the data buffer being passed in.On exit, the size of data\r
+  @param[in, out] CommBuffer     A pointer to the buffer to convey into SMRAM.\r
+  @param[in, out] CommSize       The size of the data buffer being passed in. On exit, the size of data\r
                                  being returned. Zero if the handler does not wish to reply with any data.\r
                                  being returned. Zero if the handler does not wish to reply with any data.\r
+                                 This parameter is optional and may be NULL.\r
 \r
   @retval EFI_SUCCESS            The message was successfully posted.\r
   @retval EFI_INVALID_PARAMETER  The CommBuffer was NULL.\r
 \r
   @retval EFI_SUCCESS            The message was successfully posted.\r
   @retval EFI_INVALID_PARAMETER  The CommBuffer was NULL.\r
+  @retval EFI_BAD_BUFFER_SIZE    The buffer is too large for the MM implementation.\r
+                                 If this error is returned, the MessageLength field\r
+                                 in the CommBuffer header or the integer pointed by\r
+                                 CommSize, are updated to reflect the maximum payload\r
+                                 size the implementation can accommodate.\r
+  @retval EFI_ACCESS_DENIED      The CommunicateBuffer parameter or CommSize parameter,\r
+                                 if not omitted, are in address range that cannot be\r
+                                 accessed by the MM environment.\r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 SmmCommunicationCommunicate (\r
   IN CONST EFI_SMM_COMMUNICATION_PROTOCOL  *This,\r
   IN OUT VOID                              *CommBuffer,\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 SmmCommunicationCommunicate (\r
   IN CONST EFI_SMM_COMMUNICATION_PROTOCOL  *This,\r
   IN OUT VOID                              *CommBuffer,\r
-  IN OUT UINTN                             *CommSize\r
+  IN OUT UINTN                             *CommSize OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
   EFI_SMM_COMMUNICATE_HEADER  *CommunicateHeader;\r
   BOOLEAN                     OldInSmm;\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
   EFI_SMM_COMMUNICATE_HEADER  *CommunicateHeader;\r
   BOOLEAN                     OldInSmm;\r
+  UINTN                       TempCommSize;\r
 \r
   //\r
   // Check parameters\r
   //\r
 \r
   //\r
   // Check parameters\r
   //\r
-  if ((CommBuffer == NULL) || (CommSize == NULL)) {\r
+  if (CommBuffer == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  //\r
-  // CommSize must hold HeaderGuid and MessageLength\r
-  //\r
-  if (*CommSize < OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) {\r
-    return EFI_INVALID_PARAMETER;\r
+  CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) CommBuffer;\r
+\r
+  if (CommSize == NULL) {\r
+    TempCommSize = OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + CommunicateHeader->MessageLength;\r
+  } else {\r
+    TempCommSize = *CommSize;\r
+    //\r
+    // CommSize must hold HeaderGuid and MessageLength\r
+    //\r
+    if (TempCommSize < OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -481,7 +499,7 @@ SmmCommunicationCommunicate (
     // Put arguments for Software SMI in gSmmCorePrivate\r
     //\r
     gSmmCorePrivate->CommunicationBuffer = CommBuffer;\r
     // Put arguments for Software SMI in gSmmCorePrivate\r
     //\r
     gSmmCorePrivate->CommunicationBuffer = CommBuffer;\r
-    gSmmCorePrivate->BufferSize          = *CommSize;\r
+    gSmmCorePrivate->BufferSize          = TempCommSize;\r
 \r
     //\r
     // Generate Software SMI\r
 \r
     //\r
     // Generate Software SMI\r
@@ -494,15 +512,17 @@ SmmCommunicationCommunicate (
     //\r
     // Return status from software SMI \r
     //\r
     //\r
     // Return status from software SMI \r
     //\r
-    *CommSize = gSmmCorePrivate->BufferSize;\r
+    if (CommSize != NULL) {\r
+      *CommSize = gSmmCorePrivate->BufferSize;\r
+    }\r
     return gSmmCorePrivate->ReturnStatus;\r
   }\r
 \r
   //\r
   // If we are in SMM, then the execution mode must be physical, which means that\r
   // OS established virtual addresses can not be used.  If SetVirtualAddressMap()\r
     return gSmmCorePrivate->ReturnStatus;\r
   }\r
 \r
   //\r
   // If we are in SMM, then the execution mode must be physical, which means that\r
   // OS established virtual addresses can not be used.  If SetVirtualAddressMap()\r
-  // has been called, then a direct invocation of the Software SMI is not \r
-  // not allowed so return EFI_INVALID_PARAMETER.\r
+  // has been called, then a direct invocation of the Software SMI is not allowed,\r
+  // so return EFI_INVALID_PARAMETER.\r
   //\r
   if (EfiGoneVirtual()) {\r
     return EFI_INVALID_PARAMETER;\r
   //\r
   if (EfiGoneVirtual()) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -524,20 +544,17 @@ SmmCommunicationCommunicate (
   //\r
   // Before SetVirtualAddressMap(), we are in SMM or SMRAM is open and unlocked, call SmiManage() directly.\r
   //\r
   //\r
   // Before SetVirtualAddressMap(), we are in SMM or SMRAM is open and unlocked, call SmiManage() directly.\r
   //\r
-  CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommBuffer;\r
-  *CommSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
+  TempCommSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
   Status = gSmmCorePrivate->Smst->SmiManage (\r
                                     &CommunicateHeader->HeaderGuid, \r
                                     NULL, \r
                                     CommunicateHeader->Data, \r
   Status = gSmmCorePrivate->Smst->SmiManage (\r
                                     &CommunicateHeader->HeaderGuid, \r
                                     NULL, \r
                                     CommunicateHeader->Data, \r
-                                    CommSize\r
+                                    &TempCommSize\r
                                     );\r
                                     );\r
-\r
-  //\r
-  // Update CommunicationBuffer, BufferSize and ReturnStatus\r
-  // Communicate service finished, reset the pointer to CommBuffer to NULL\r
-  //\r
-  *CommSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
+  TempCommSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
+  if (CommSize != NULL) {\r
+    *CommSize = TempCommSize;\r
+  }\r
 \r
   //\r
   // Restore original InSmm state\r
 \r
   //\r
   // Restore original InSmm state\r