]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg PiSmmIpl: Handle CommSize OPTIONAL case
authorStar Zeng <star.zeng@intel.com>
Tue, 7 Nov 2017 05:42:21 +0000 (13:42 +0800)
committerStar Zeng <star.zeng@intel.com>
Thu, 7 Dec 2017 09:40:25 +0000 (17:40 +0800)
Handle CommSize OPTIONAL case for SmmCommunicate.
And return EFI_ACCESS_DENIED when CommunicationBuffer
is not valid for SMM to access.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c

index a7467aca201229dfb9511540ec7f02641e285945..4c1e3e7195241349b926d46d1fcc8a48b80d76fb 100644 (file)
@@ -544,7 +544,7 @@ SmmEntryPoint (
         // return EFI_INVALID_PARAMETER\r
         //\r
         gSmmCorePrivate->CommunicationBuffer = NULL;\r
-        gSmmCorePrivate->ReturnStatus = EFI_INVALID_PARAMETER;\r
+        gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;\r
       } else {\r
         CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;\r
         BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
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