]> 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
-  @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
+                                 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
+  @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
-  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
+  UINTN                       TempCommSize;\r
 \r
   //\r
   // Check parameters\r
   //\r
-  if ((CommBuffer == NULL) || (CommSize == NULL)) {\r
+  if (CommBuffer == NULL) {\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
@@ -481,7 +499,7 @@ SmmCommunicationCommunicate (
     // 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
@@ -494,15 +512,17 @@ SmmCommunicationCommunicate (
     //\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
-  // 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
@@ -524,20 +544,17 @@ SmmCommunicationCommunicate (
   //\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
-                                    CommSize\r
+                                    &TempCommSize\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