]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / Image.c
index 341a50a7e8f3303126f0b914e9a3621fdb0727a2..bd623cae152881c7190fafae69f85f3b1f383e22 100644 (file)
@@ -1,87 +1,62 @@
 /** @file\r
+Implementation for EFI_HII_IMAGE_PROTOCOL.\r
 \r
-Copyright (c) 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
-    Image.c\r
-\r
-Abstract:\r
-\r
-    Implementation for EFI_HII_IMAGE_PROTOCOL.\r
-\r
-Revision History\r
 \r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 \r
 #include "HiiDatabase.h"\r
 \r
-#ifndef DISABLE_UNUSED_HII_PROTOCOLS\r
+#define MAX_UINT24    0xFFFFFF\r
 \r
-STATIC\r
-UINT8*\r
-GetImageIdOrAddress (\r
-  IN  UINT8           *ImageBlock,\r
-  IN OUT EFI_IMAGE_ID *ImageId\r
-  )\r
-/*++\r
+/**\r
+  Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input\r
+  ImageId is zero, otherwise return the address of the\r
+  corresponding image block with identifier specified by ImageId.\r
 \r
-  Routine Description:\r
-    Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input\r
-    ImageId is zero, otherwise return the address of the\r
-    corresponding image block with identifier specified by ImageId.\r
+  This is a internal function.\r
 \r
-  Arguments:\r
-    ImageBlock     - Points to the beginning of a series of image blocks stored in order.\r
-    ImageId        - If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;\r
-                     else use this id to find its corresponding image block address.\r
+  @param ImageBlocks     Points to the beginning of a series of image blocks stored in order.\r
+  @param ImageId         If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;\r
+                         else use this id to find its corresponding image block address.\r
 \r
-  Returns:\r
-    The image block address when input ImageId is not zero; otherwise return NULL.\r
+  @return The image block address when input ImageId is not zero; otherwise return NULL.\r
 \r
---*/\r
+**/\r
+EFI_HII_IMAGE_BLOCK *\r
+GetImageIdOrAddress (\r
+  IN EFI_HII_IMAGE_BLOCK *ImageBlocks,\r
+  IN OUT EFI_IMAGE_ID    *ImageId\r
+  )\r
 {\r
   EFI_IMAGE_ID                   ImageIdCurrent;\r
-  UINT8                          *ImageBlockHdr;\r
-  UINT8                          Length8;\r
-  UINT16                         Length16;\r
-  UINT32                         Length32;\r
-  EFI_HII_IIBT_IMAGE_1BIT_BLOCK  Iibt1bit;\r
-  EFI_HII_IIBT_IMAGE_4BIT_BLOCK  Iibt4bit;\r
-  EFI_HII_IIBT_IMAGE_8BIT_BLOCK  Iibt8bit;\r
-  UINT16                         Width;\r
-  UINT16                         Height;\r
-\r
-  ASSERT (ImageBlock != NULL && ImageId != NULL);\r
-\r
-  ImageBlockHdr  = ImageBlock;\r
-  ImageIdCurrent = 1;\r
-\r
-  while (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType != EFI_HII_IIBT_END) {\r
-    if (*ImageId > 0) {\r
+  EFI_HII_IMAGE_BLOCK            *CurrentImageBlock;\r
+  UINTN                          Length;\r
+\r
+  ASSERT (ImageBlocks != NULL && ImageId != NULL);\r
+  CurrentImageBlock = ImageBlocks;\r
+  ImageIdCurrent    = 1;\r
+\r
+  while (CurrentImageBlock->BlockType != EFI_HII_IIBT_END) {\r
+    if (*ImageId != 0) {\r
       if (*ImageId == ImageIdCurrent) {\r
         //\r
         // If the found image block is a duplicate block, update the ImageId to\r
         // find the previous defined image block.\r
         //\r
-        if (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType == EFI_HII_IIBT_DUPLICATE) {\r
-          CopyMem (ImageId, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (EFI_IMAGE_ID));\r
+        if (CurrentImageBlock->BlockType == EFI_HII_IIBT_DUPLICATE) {\r
+          *ImageId = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_DUPLICATE_BLOCK *) CurrentImageBlock)->ImageId);\r
           ASSERT (*ImageId != ImageIdCurrent);\r
-          ImageBlock = ImageBlockHdr;\r
+          ASSERT (*ImageId != 0);\r
+          CurrentImageBlock = ImageBlocks;\r
           ImageIdCurrent = 1;\r
           continue;\r
         }\r
 \r
-        return ImageBlock;\r
+        return CurrentImageBlock;\r
       }\r
       if (*ImageId < ImageIdCurrent) {\r
         //\r
@@ -90,89 +65,80 @@ GetImageIdOrAddress (
         return NULL;\r
       }\r
     }\r
-    switch (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType) {\r
+    switch (CurrentImageBlock->BlockType) {\r
     case EFI_HII_IIBT_EXT1:\r
-      Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8));\r
-      ImageBlock += Length8;\r
-      ImageIdCurrent++;\r
+      Length = ((EFI_HII_IIBT_EXT1_BLOCK *) CurrentImageBlock)->Length;\r
       break;\r
     case EFI_HII_IIBT_EXT2:\r
-      CopyMem (\r
-        &Length16,\r
-        ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),\r
-        sizeof (UINT16)\r
-        );\r
-      ImageBlock += Length16;\r
-      ImageIdCurrent++;\r
+      Length = ReadUnaligned16 (&((EFI_HII_IIBT_EXT2_BLOCK *) CurrentImageBlock)->Length);\r
       break;\r
     case EFI_HII_IIBT_EXT4:\r
-      CopyMem (\r
-        &Length32,\r
-        ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8),\r
-        sizeof (UINT32)\r
-        );\r
-      ImageBlock += Length32;\r
-      ImageIdCurrent++;\r
+      Length = ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_EXT4_BLOCK *) CurrentImageBlock)->Length);\r
       break;\r
 \r
     case EFI_HII_IIBT_IMAGE_1BIT:\r
     case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
-      CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
-      ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +\r
-                    BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);\r
+      Length = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +\r
+               BITMAP_LEN_1_BIT (\r
+                 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),\r
+                 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)\r
+                 );\r
       ImageIdCurrent++;\r
       break;\r
 \r
     case EFI_HII_IIBT_IMAGE_4BIT:\r
     case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
-      CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));\r
-      ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +\r
-                    BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);\r
+      Length = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +\r
+               BITMAP_LEN_4_BIT (\r
+                 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),\r
+                 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)\r
+                 );\r
       ImageIdCurrent++;\r
       break;\r
 \r
     case EFI_HII_IIBT_IMAGE_8BIT:\r
     case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
-      CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));\r
-      ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +\r
-                    BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);\r
+      Length = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +\r
+               BITMAP_LEN_8_BIT (\r
+                 (UINT32) ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),\r
+                 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)\r
+                 );\r
       ImageIdCurrent++;\r
       break;\r
 \r
     case EFI_HII_IIBT_IMAGE_24BIT:\r
     case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
-      CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
-      CopyMem (\r
-        &Height,\r
-        ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
-        sizeof (UINT16)\r
-        );\r
-      ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
-                    BITMAP_LEN_24_BIT (Width, Height);\r
+      Length = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
+               BITMAP_LEN_24_BIT (\r
+                 (UINT32) ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),\r
+                 ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)\r
+                 );\r
       ImageIdCurrent++;\r
       break;\r
 \r
     case EFI_HII_IIBT_DUPLICATE:\r
-      ImageBlock += sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);\r
+      Length = sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);\r
       ImageIdCurrent++;\r
       break;\r
 \r
     case EFI_HII_IIBT_IMAGE_JPEG:\r
-      CopyMem (&Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT32));\r
-      ImageBlock += Length32;\r
+      Length = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size);\r
+      ImageIdCurrent++;\r
+      break;\r
+\r
+    case EFI_HII_IIBT_IMAGE_PNG:\r
+      Length = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Size);\r
       ImageIdCurrent++;\r
       break;\r
 \r
     case EFI_HII_IIBT_SKIP1:\r
-      Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK));\r
-      ImageBlock += sizeof (EFI_HII_IIBT_SKIP1_BLOCK);\r
-      ImageIdCurrent = (UINT16) (ImageIdCurrent + Length8);\r
+      Length = sizeof (EFI_HII_IIBT_SKIP1_BLOCK);\r
+      ImageIdCurrent += ((EFI_HII_IIBT_SKIP1_BLOCK *) CurrentImageBlock)->SkipCount;\r
       break;\r
 \r
     case EFI_HII_IIBT_SKIP2:\r
-      CopyMem (&Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
-      ImageBlock += sizeof (EFI_HII_IIBT_SKIP2_BLOCK);\r
-      ImageIdCurrent = (UINT16) (ImageIdCurrent + Length16);\r
+      Length = sizeof (EFI_HII_IIBT_SKIP2_BLOCK);\r
+      ImageIdCurrent += ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_SKIP2_BLOCK *) CurrentImageBlock)->SkipCount);\r
       break;\r
 \r
     default:\r
@@ -180,7 +146,12 @@ GetImageIdOrAddress (
       // Unknown image blocks can not be skipped, processing halts.\r
       //\r
       ASSERT (FALSE);\r
+      Length = 0;\r
+      break;\r
     }\r
+\r
+    CurrentImageBlock = (EFI_HII_IMAGE_BLOCK *) ((UINT8 *) CurrentImageBlock + Length);\r
+\r
   }\r
 \r
   //\r
@@ -188,7 +159,7 @@ GetImageIdOrAddress (
   //\r
   if (*ImageId == 0) {\r
     *ImageId = ImageIdCurrent;\r
-    return ImageBlock;\r
+    return CurrentImageBlock;\r
   }\r
 \r
   return NULL;\r
@@ -199,13 +170,15 @@ GetImageIdOrAddress (
 /**\r
   Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.\r
 \r
+  This is a internal function.\r
+\r
+\r
   @param  BitMapOut              Pixels in EFI_HII_RGB_PIXEL format.\r
   @param  BitMapIn               Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.\r
   @param  PixelNum               The number of pixels to be converted.\r
 \r
 \r
 **/\r
-STATIC\r
 VOID\r
 CopyGopToRgbPixel (\r
   OUT EFI_HII_RGB_PIXEL              *BitMapOut,\r
@@ -226,13 +199,15 @@ CopyGopToRgbPixel (
 /**\r
   Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.\r
 \r
+  This is a internal function.\r
+\r
+\r
   @param  BitMapOut              Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.\r
   @param  BitMapIn               Pixels in EFI_HII_RGB_PIXEL format.\r
   @param  PixelNum               The number of pixels to be converted.\r
 \r
 \r
 **/\r
-STATIC\r
 VOID\r
 CopyRgbToGopPixel (\r
   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BitMapOut,\r
@@ -253,6 +228,9 @@ CopyRgbToGopPixel (
 /**\r
   Output pixels in "1 bit per pixel" format to an image.\r
 \r
+  This is a internal function.\r
+\r
+\r
   @param  Image                  Points to the image which will store the pixels.\r
   @param  Data                   Stores the value of output pixels, 0 or 1.\r
   @param  PaletteInfo            PaletteInfo which stores the color of the output\r
@@ -261,7 +239,6 @@ CopyRgbToGopPixel (
 \r
 \r
 **/\r
-STATIC\r
 VOID\r
 Output1bitPixel (\r
   IN OUT EFI_IMAGE_INPUT             *Image,\r
@@ -269,14 +246,14 @@ Output1bitPixel (
   IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo\r
   )\r
 {\r
-  UINT16                             X;\r
-  UINT16                             Y;\r
+  UINT16                             Xpos;\r
+  UINT16                             Ypos;\r
   UINTN                              OffsetY;\r
   UINT8                              Index;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[2];\r
   EFI_HII_IMAGE_PALETTE_INFO         *Palette;\r
-  UINT16                             PaletteSize;\r
+  UINT                             PaletteSize;\r
   UINT8                              Byte;\r
 \r
   ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);\r
@@ -286,32 +263,36 @@ Output1bitPixel (
   //\r
   // First entry corresponds to color 0 and second entry corresponds to color 1.\r
   //\r
+  PaletteSize = 0;\r
   CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
   PaletteSize += sizeof (UINT16);\r
   Palette = AllocateZeroPool (PaletteSize);\r
   ASSERT (Palette != NULL);\r
+  if (Palette == NULL) {\r
+    return;\r
+  }\r
   CopyMem (Palette, PaletteInfo, PaletteSize);\r
 \r
   ZeroMem (PaletteValue, sizeof (PaletteValue));\r
   CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);\r
   CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);\r
-  SafeFreePool (Palette);\r
+  FreePool (Palette);\r
 \r
   //\r
   // Convert the pixel from one bit to corresponding color.\r
   //\r
-  for (Y = 0; Y < Image->Height; Y++) {\r
-    OffsetY = BITMAP_LEN_1_BIT (Image->Width, Y);\r
+  for (Ypos = 0; Ypos < Image->Height; Ypos++) {\r
+    OffsetY = BITMAP_LEN_1_BIT (Image->Width, Ypos);\r
     //\r
     // All bits in these bytes are meaningful\r
     //\r
-    for (X = 0; X < Image->Width / 8; X++) {\r
-      Byte = *(Data + OffsetY + X);\r
+    for (Xpos = 0; Xpos < Image->Width / 8; Xpos++) {\r
+      Byte = *(Data + OffsetY + Xpos);\r
       for (Index = 0; Index < 8; Index++) {\r
         if ((Byte & (1 << Index)) != 0) {\r
-          BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[1];\r
+          BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1];\r
         } else {\r
-          BitMapPtr[Y * Image->Width + X * 8 + (8 - Index - 1)] = PaletteValue[0];\r
+          BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0];\r
         }\r
       }\r
     }\r
@@ -320,12 +301,12 @@ Output1bitPixel (
       //\r
       // Padding bits in this byte should be ignored.\r
       //\r
-      Byte = *(Data + OffsetY + X);\r
+      Byte = *(Data + OffsetY + Xpos);\r
       for (Index = 0; Index < Image->Width % 8; Index++) {\r
         if ((Byte & (1 << (8 - Index - 1))) != 0) {\r
-          BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[1];\r
+          BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1];\r
         } else {\r
-          BitMapPtr[Y * Image->Width + X * 8 + Index] = PaletteValue[0];\r
+          BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0];\r
         }\r
       }\r
     }\r
@@ -336,15 +317,17 @@ Output1bitPixel (
 /**\r
   Output pixels in "4 bit per pixel" format to an image.\r
 \r
+  This is a internal function.\r
+\r
+\r
   @param  Image                  Points to the image which will store the pixels.\r
   @param  Data                   Stores the value of output pixels, 0 ~ 15.\r
-  @param  PaletteInfo            PaletteInfo which stores the color of the output\r
+  @param[in]  PaletteInfo            PaletteInfo which stores the color of the output\r
                                  pixels. Each entry corresponds to a color within\r
                                  [0, 15].\r
 \r
 \r
 **/\r
-STATIC\r
 VOID\r
 Output4bitPixel (\r
   IN OUT EFI_IMAGE_INPUT             *Image,\r
@@ -352,13 +335,13 @@ Output4bitPixel (
   IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo\r
   )\r
 {\r
-  UINT16                             X;\r
-  UINT16                             Y;\r
+  UINT16                             Xpos;\r
+  UINT16                             Ypos;\r
   UINTN                              OffsetY;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[16];\r
   EFI_HII_IMAGE_PALETTE_INFO         *Palette;\r
-  UINT16                             PaletteSize;\r
+  UINT                             PaletteSize;\r
   UINT16                             PaletteNum;\r
   UINT8                              Byte;\r
 \r
@@ -369,37 +352,41 @@ Output4bitPixel (
   //\r
   // The bitmap should allocate each color index starting from 0.\r
   //\r
+  PaletteSize = 0;\r
   CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
   PaletteSize += sizeof (UINT16);\r
   Palette = AllocateZeroPool (PaletteSize);\r
   ASSERT (Palette != NULL);\r
+  if (Palette == NULL) {\r
+    return;\r
+  }\r
   CopyMem (Palette, PaletteInfo, PaletteSize);\r
   PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));\r
 \r
   ZeroMem (PaletteValue, sizeof (PaletteValue));\r
-  CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);\r
-  SafeFreePool (Palette);\r
+  CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));\r
+  FreePool (Palette);\r
 \r
   //\r
   // Convert the pixel from 4 bit to corresponding color.\r
   //\r
-  for (Y = 0; Y < Image->Height; Y++) {\r
-    OffsetY = BITMAP_LEN_4_BIT (Image->Width, Y);\r
+  for (Ypos = 0; Ypos < Image->Height; Ypos++) {\r
+    OffsetY = BITMAP_LEN_4_BIT (Image->Width, Ypos);\r
     //\r
     // All bits in these bytes are meaningful\r
     //\r
-    for (X = 0; X < Image->Width / 2; X++) {\r
-      Byte = *(Data + OffsetY + X);\r
-      BitMapPtr[Y * Image->Width + X * 2]     = PaletteValue[Byte >> 4];\r
-      BitMapPtr[Y * Image->Width + X * 2 + 1] = PaletteValue[Byte & 0x0F];\r
+    for (Xpos = 0; Xpos < Image->Width / 2; Xpos++) {\r
+      Byte = *(Data + OffsetY + Xpos);\r
+      BitMapPtr[Ypos * Image->Width + Xpos * 2]     = PaletteValue[Byte >> 4];\r
+      BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1] = PaletteValue[Byte & 0x0F];\r
     }\r
 \r
     if (Image->Width % 2 != 0) {\r
       //\r
       // Padding bits in this byte should be ignored.\r
       //\r
-      Byte = *(Data + OffsetY + X);\r
-      BitMapPtr[Y * Image->Width + X * 2]     = PaletteValue[Byte >> 4];\r
+      Byte = *(Data + OffsetY + Xpos);\r
+      BitMapPtr[Ypos * Image->Width + Xpos * 2]     = PaletteValue[Byte >> 4];\r
     }\r
   }\r
 }\r
@@ -408,15 +395,17 @@ Output4bitPixel (
 /**\r
   Output pixels in "8 bit per pixel" format to an image.\r
 \r
+  This is a internal function.\r
+\r
+\r
   @param  Image                  Points to the image which will store the pixels.\r
   @param  Data                   Stores the value of output pixels, 0 ~ 255.\r
-  @param  PaletteInfo            PaletteInfo which stores the color of the output\r
+  @param[in]  PaletteInfo        PaletteInfo which stores the color of the output\r
                                  pixels. Each entry corresponds to a color within\r
                                  [0, 255].\r
 \r
 \r
 **/\r
-STATIC\r
 VOID\r
 Output8bitPixel (\r
   IN OUT EFI_IMAGE_INPUT             *Image,\r
@@ -424,13 +413,13 @@ Output8bitPixel (
   IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo\r
   )\r
 {\r
-  UINT16                             X;\r
-  UINT16                             Y;\r
+  UINT16                             Xpos;\r
+  UINT16                             Ypos;\r
   UINTN                              OffsetY;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[256];\r
   EFI_HII_IMAGE_PALETTE_INFO         *Palette;\r
-  UINT16                             PaletteSize;\r
+  UINT                             PaletteSize;\r
   UINT16                             PaletteNum;\r
   UINT8                              Byte;\r
 \r
@@ -441,27 +430,31 @@ Output8bitPixel (
   //\r
   // The bitmap should allocate each color index starting from 0.\r
   //\r
+  PaletteSize = 0;\r
   CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
   PaletteSize += sizeof (UINT16);\r
   Palette = AllocateZeroPool (PaletteSize);\r
   ASSERT (Palette != NULL);\r
+  if (Palette == NULL) {\r
+    return;\r
+  }\r
   CopyMem (Palette, PaletteInfo, PaletteSize);\r
   PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));\r
   ZeroMem (PaletteValue, sizeof (PaletteValue));\r
-  CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);\r
-  SafeFreePool (Palette);\r
+  CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));\r
+  FreePool (Palette);\r
 \r
   //\r
   // Convert the pixel from 8 bits to corresponding color.\r
   //\r
-  for (Y = 0; Y < Image->Height; Y++) {\r
-    OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);\r
+  for (Ypos = 0; Ypos < Image->Height; Ypos++) {\r
+    OffsetY = BITMAP_LEN_8_BIT ((UINT32) Image->Width, Ypos);\r
     //\r
     // All bits are meaningful since the bitmap is 8 bits per pixel.\r
     //\r
-    for (X = 0; X < Image->Width; X++) {\r
-      Byte = *(Data + OffsetY + X);\r
-      BitMapPtr[OffsetY + X] = PaletteValue[Byte];\r
+    for (Xpos = 0; Xpos < Image->Width; Xpos++) {\r
+      Byte = *(Data + OffsetY + Xpos);\r
+      BitMapPtr[OffsetY + Xpos] = PaletteValue[Byte];\r
     }\r
   }\r
 \r
@@ -471,20 +464,22 @@ Output8bitPixel (
 /**\r
   Output pixels in "24 bit per pixel" format to an image.\r
 \r
+  This is a internal function.\r
+\r
+\r
   @param  Image                  Points to the image which will store the pixels.\r
   @param  Data                   Stores the color of output pixels, allowing 16.8\r
                                  millions colors.\r
 \r
 \r
 **/\r
-STATIC\r
 VOID\r
 Output24bitPixel (\r
   IN OUT EFI_IMAGE_INPUT             *Image,\r
   IN EFI_HII_RGB_PIXEL               *Data\r
   )\r
 {\r
-  UINT16                             Y;\r
+  UINT16                             Ypos;\r
   UINTN                              OffsetY;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;\r
 \r
@@ -492,8 +487,8 @@ Output24bitPixel (
 \r
   BitMapPtr = Image->Bitmap;\r
 \r
-  for (Y = 0; Y < Image->Height; Y++) {\r
-    OffsetY = BITMAP_LEN_8_BIT (Image->Width, Y);\r
+  for (Ypos = 0; Ypos < Image->Height; Ypos++) {\r
+    OffsetY = BITMAP_LEN_8_BIT ((UINT32) Image->Width, Ypos);\r
     CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);\r
   }\r
 \r
@@ -503,7 +498,12 @@ Output24bitPixel (
 /**\r
   Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.\r
 \r
+  This is a internal function.\r
+\r
+\r
   @param  BltBuffer              Buffer points to bitmap data of incoming image.\r
+  @param  BltX                   Specifies the offset from the left and top edge of\r
+                                  the output image of the first pixel in the image.\r
   @param  BltY                   Specifies the offset from the left and top edge of\r
                                   the output image of the first pixel in the image.\r
   @param  Width                  Width of the incoming image, in pixels.\r
@@ -517,7 +517,6 @@ Output24bitPixel (
   @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 ImageToBlt (\r
   IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,\r
@@ -530,8 +529,8 @@ ImageToBlt (
   )\r
 {\r
   EFI_IMAGE_OUTPUT                   *ImageOut;\r
-  UINTN                              X;\r
-  UINTN                              Y;\r
+  UINTN                              Xpos;\r
+  UINTN                              Ypos;\r
   UINTN                              OffsetY1; // src buffer\r
   UINTN                              OffsetY2; // dest buffer\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      SrcPixel;\r
@@ -552,17 +551,17 @@ ImageToBlt (
 \r
   ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
 \r
-  for (Y = 0; Y < Height; Y++) {\r
-    OffsetY1 = Width * Y;\r
-    OffsetY2 = ImageOut->Width * (BltY + Y);\r
-    for (X = 0; X < Width; X++) {\r
-      SrcPixel = BltBuffer[OffsetY1 + X];\r
+  for (Ypos = 0; Ypos < Height; Ypos++) {\r
+    OffsetY1 = Width * Ypos;\r
+    OffsetY2 = ImageOut->Width * (BltY + Ypos);\r
+    for (Xpos = 0; Xpos < Width; Xpos++) {\r
+      SrcPixel = BltBuffer[OffsetY1 + Xpos];\r
       if (Transparent) {\r
         if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {\r
-          ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;\r
+          ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;\r
         }\r
       } else {\r
-        ImageOut->Image.Bitmap[OffsetY2 + BltX + X] = SrcPixel;\r
+        ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;\r
       }\r
     }\r
   }\r
@@ -570,6 +569,37 @@ ImageToBlt (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Return the HII package list identified by PackageList HII handle.\r
+\r
+  @param Database    Pointer to HII database list header.\r
+  @param PackageList HII handle of the package list to locate.\r
+\r
+  @retval The HII package list instance.\r
+**/\r
+HII_DATABASE_PACKAGE_LIST_INSTANCE *\r
+LocatePackageList (\r
+  IN  LIST_ENTRY                     *Database,\r
+  IN  EFI_HII_HANDLE                 PackageList\r
+  )\r
+{\r
+  LIST_ENTRY                         *Link;\r
+  HII_DATABASE_RECORD                *Record;\r
+\r
+  //\r
+  // Get the specified package list and image package.\r
+  //\r
+  for (Link = GetFirstNode (Database);\r
+       !IsNull (Database, Link);\r
+       Link = GetNextNode (Database, Link)\r
+      ) {\r
+    Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if (Record->Handle == PackageList) {\r
+      return Record->PackageList;\r
+    }\r
+  }\r
+  return NULL;\r
+}\r
 \r
 /**\r
   This function adds the image Image to the group of images owned by PackageList, and returns\r
@@ -599,52 +629,33 @@ HiiNewImage (
   )\r
 {\r
   HII_DATABASE_PRIVATE_DATA           *Private;\r
-  LIST_ENTRY                          *Link;\r
-  HII_DATABASE_RECORD                 *DatabaseRecord;\r
   HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
   HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;\r
-  UINT8                               *ImageBlock;\r
-  UINTN                               BlockSize;\r
-  UINT8                               *NewBlock;\r
-  UINT8                               *NewBlockPtr;\r
-  UINTN                               NewBlockSize;\r
-  EFI_IMAGE_INPUT                     *ImageIn;\r
-\r
-  if (This == NULL || ImageId == NULL || Image == NULL || PackageList == NULL) {\r
+  EFI_HII_IMAGE_BLOCK                 *ImageBlocks;\r
+  UINT32                              NewBlockSize;\r
+\r
+  if (This == NULL || ImageId == NULL || Image == NULL || Image->Bitmap == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (!IsHiiHandleValid (PackageList)) {\r
+  Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);\r
+  if (PackageListNode == NULL) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  EfiAcquireLock (&mHiiDatabaseLock);\r
 \r
   //\r
-  // Get the specified package list\r
+  // Calcuate the size of new image.\r
+  // Make sure the size doesn't overflow UINT32.\r
+  // Note: 24Bit BMP occpuies 3 bytes per pixel.\r
   //\r
-\r
-  PackageListNode = NULL;\r
-\r
-  for (Link = Private->DatabaseList.ForwardLink;\r
-       Link != &Private->DatabaseList;\r
-       Link = Link->ForwardLink\r
-      ) {\r
-    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
-    if (DatabaseRecord->Handle == PackageList) {\r
-      PackageListNode = DatabaseRecord->PackageList;\r
-      break;\r
-    }\r
-  }\r
-\r
-  if (PackageListNode == NULL) {\r
-    return EFI_NOT_FOUND;\r
+  NewBlockSize = (UINT32)Image->Width * Image->Height;\r
+  if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
-\r
-  ImageIn = (EFI_IMAGE_INPUT *) Image;\r
-\r
-  NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
-                 BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);\r
+  NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));\r
 \r
   //\r
   // Get the image package in the package list,\r
@@ -663,47 +674,62 @@ HiiNewImage (
     //\r
     // Update the package's image block by appending the new block to the end.\r
     //\r
-    BlockSize  = ImagePackage->ImageBlockSize + NewBlockSize;\r
-    ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
-    if (ImageBlock == NULL) {\r
+\r
+    //\r
+    // Make sure the final package length doesn't overflow.\r
+    // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.\r
+    //\r
+    if (NewBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,\r
+    // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24\r
+    //\r
+    ImageBlocks = AllocatePool (ImagePackage->ImageBlockSize + NewBlockSize);\r
+    if (ImageBlocks == NULL) {\r
+      EfiReleaseLock (&mHiiDatabaseLock);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
     //\r
     // Copy the original content.\r
     //\r
     CopyMem (\r
-      ImageBlock,\r
+      ImageBlocks,\r
       ImagePackage->ImageBlock,\r
       ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)\r
       );\r
-    SafeFreePool (ImagePackage->ImageBlock);\r
-    ImagePackage->ImageBlock = ImageBlock;\r
-    ImageBlock += ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK);\r
+    FreePool (ImagePackage->ImageBlock);\r
+    ImagePackage->ImageBlock = ImageBlocks;\r
+\r
     //\r
-    // Temp memory to store new block.\r
+    // Point to the very last block.\r
     //\r
-    NewBlock = AllocateZeroPool (NewBlockSize);\r
-    if (NewBlock == NULL) {\r
-      SafeFreePool (ImagePackage->ImageBlock);\r
-      ImagePackage->ImageBlock = NULL;\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-    NewBlockPtr = NewBlock;\r
-\r
+    ImageBlocks = (EFI_HII_IMAGE_BLOCK *) (\r
+                    (UINT8 *) ImageBlocks + ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)\r
+                    );\r
     //\r
     // Update the length record.\r
     //\r
-    ImagePackage->ImageBlockSize = (UINT32) BlockSize;\r
-    ImagePackage->ImagePkgHdr.Header.Length += (UINT32) NewBlockSize;\r
-    PackageListNode->PackageListHdr.PackageLength += (UINT32) NewBlockSize;\r
+    ImagePackage->ImageBlockSize                  += NewBlockSize;\r
+    ImagePackage->ImagePkgHdr.Header.Length       += NewBlockSize;\r
+    PackageListNode->PackageListHdr.PackageLength += NewBlockSize;\r
 \r
   } else {\r
+    //\r
+    // Make sure the final package length doesn't overflow.\r
+    // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.\r
+    //\r
+    if (NewBlockSize > MAX_UINT24 - (sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + sizeof (EFI_HII_IIBT_END_BLOCK))) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
     //\r
     // The specified package list does not contain image package.\r
     // Create one to add this image block.\r
     //\r
     ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));\r
     if (ImagePackage == NULL) {\r
+      EfiReleaseLock (&mHiiDatabaseLock);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
     //\r
@@ -711,11 +737,10 @@ HiiNewImage (
     // first image block so that id is initially to one.\r
     //\r
     *ImageId = 1;\r
-    BlockSize    = sizeof (EFI_HII_IIBT_END_BLOCK) + NewBlockSize;\r
     //\r
     // Fill in image package header.\r
     //\r
-    ImagePackage->ImagePkgHdr.Header.Length     = (UINT32) BlockSize + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
+    ImagePackage->ImagePkgHdr.Header.Length     = sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);\r
     ImagePackage->ImagePkgHdr.Header.Type       = EFI_HII_PACKAGE_IMAGES;\r
     ImagePackage->ImagePkgHdr.ImageInfoOffset   = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);\r
     ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;\r
@@ -729,24 +754,14 @@ HiiNewImage (
     //\r
     // Fill in image blocks.\r
     //\r
-    ImagePackage->ImageBlockSize = (UINT32) BlockSize;\r
-    ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);\r
+    ImagePackage->ImageBlockSize = NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);\r
+    ImagePackage->ImageBlock = AllocateZeroPool (NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK));\r
     if (ImagePackage->ImageBlock == NULL) {\r
-      SafeFreePool (ImagePackage);\r
+      FreePool (ImagePackage);\r
+      EfiReleaseLock (&mHiiDatabaseLock);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
-    ImageBlock = ImagePackage->ImageBlock;\r
-\r
-    //\r
-    // Temp memory to store new block.\r
-    //\r
-    NewBlock = AllocateZeroPool (NewBlockSize);\r
-    if (NewBlock == NULL) {\r
-      SafeFreePool (ImagePackage->ImageBlock);\r
-      SafeFreePool (ImagePackage);\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-    NewBlockPtr = NewBlock;\r
+    ImageBlocks = ImagePackage->ImageBlock;\r
 \r
     //\r
     // Insert this image package.\r
@@ -758,26 +773,30 @@ HiiNewImage (
   //\r
   // Append the new block here\r
   //\r
-  if (ImageIn->Flags == EFI_IMAGE_TRANSPARENT) {\r
-    *NewBlock = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
+  if (Image->Flags == EFI_IMAGE_TRANSPARENT) {\r
+    ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
   } else {\r
-    *NewBlock = EFI_HII_IIBT_IMAGE_24BIT;\r
+    ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT;\r
   }\r
-  NewBlock++;\r
-  CopyMem (NewBlock, &ImageIn->Width, sizeof (UINT16));\r
-  NewBlock += sizeof (UINT16);\r
-  CopyMem (NewBlock, &ImageIn->Height, sizeof (UINT16));\r
-  NewBlock += sizeof (UINT16);\r
-  CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlock, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);\r
-\r
-  CopyMem (ImageBlock, NewBlockPtr, NewBlockSize);\r
-  SafeFreePool (NewBlockPtr);\r
+  WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Width, Image->Width);\r
+  WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Height, Image->Height);\r
+  CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Bitmap, Image->Bitmap, (UINT32) Image->Width * Image->Height);\r
 \r
   //\r
   // Append the block end\r
   //\r
-  ImageBlock += NewBlockSize;\r
-  ((EFI_HII_IIBT_END_BLOCK *) (ImageBlock))->Header.BlockType = EFI_HII_IIBT_END;\r
+  ImageBlocks = (EFI_HII_IMAGE_BLOCK *) ((UINT8 *) ImageBlocks + NewBlockSize);\r
+  ImageBlocks->BlockType = EFI_HII_IIBT_END;\r
+\r
+  //\r
+  // Check whether need to get the contents of HiiDataBase.\r
+  // Only after ReadyToBoot to do the export.\r
+  //\r
+  if (gExportAfterReadyToBoot) {\r
+    HiiGetDatabaseInfo(&Private->HiiDatabase);\r
+  }\r
+\r
+  EfiReleaseLock (&mHiiDatabaseLock);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -787,74 +806,52 @@ HiiNewImage (
   This function retrieves the image specified by ImageId which is associated with\r
   the specified PackageList and copies it into the buffer specified by Image.\r
 \r
-  @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+  @param  Database               A pointer to the database list header.\r
   @param  PackageList            Handle of the package list where this image will\r
                                  be searched.\r
   @param  ImageId                The image's id,, which is unique within\r
                                  PackageList.\r
   @param  Image                  Points to the image.\r
-  @param  ImageSize              On entry, points to the size of the buffer pointed\r
-                                 to by Image, in bytes.  On return, points to the\r
-                                 length of the image, in bytes.\r
+  @param  BitmapOnly             TRUE to only return the bitmap type image.\r
+                                 FALSE to locate image decoder instance to decode image.\r
 \r
   @retval EFI_SUCCESS            The new image was returned successfully.\r
-  @retval EFI_NOT_FOUND          The image specified by ImageId is not available.\r
+  @retval EFI_NOT_FOUND          The image specified by ImageId is not in the\r
+                                 database. The specified PackageList is not in the database.\r
   @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to\r
                                  hold the image.\r
   @retval EFI_INVALID_PARAMETER  The Image or ImageSize was NULL.\r
-\r
+  @retval EFI_OUT_OF_RESOURCES   The bitmap could not be retrieved because there was not\r
+                                 enough memory.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-HiiGetImage (\r
-  IN  CONST EFI_HII_IMAGE_PROTOCOL   *This,\r
+IGetImage (\r
+  IN  LIST_ENTRY                     *Database,\r
   IN  EFI_HII_HANDLE                 PackageList,\r
   IN  EFI_IMAGE_ID                   ImageId,\r
   OUT EFI_IMAGE_INPUT                *Image,\r
-  OUT UINTN                          *ImageSize\r
+  IN  BOOLEAN                        BitmapOnly\r
   )\r
 {\r
-  HII_DATABASE_PRIVATE_DATA           *Private;\r
-  LIST_ENTRY                          *Link;\r
-  HII_DATABASE_RECORD                 *DatabaseRecord;\r
+  EFI_STATUS                          Status;\r
   HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
   HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;\r
-  UINT8                               *ImageBlock;\r
-  EFI_IMAGE_ID                        LocalImageId;\r
-  UINT8                               BlockType;\r
+  EFI_HII_IMAGE_BLOCK                 *CurrentImageBlock;\r
   EFI_HII_IIBT_IMAGE_1BIT_BLOCK       Iibt1bit;\r
   UINT16                              Width;\r
   UINT16                              Height;\r
   UINTN                               ImageLength;\r
-  BOOLEAN                             Flag;\r
   UINT8                               *PaletteInfo;\r
   UINT8                               PaletteIndex;\r
   UINT16                              PaletteSize;\r
+  EFI_HII_IMAGE_DECODER_PROTOCOL      *Decoder;\r
+  EFI_IMAGE_OUTPUT                    *ImageOut;\r
 \r
-  if (This == NULL || ImageSize == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {\r
+  if (Image == NULL || ImageId == 0) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (!IsHiiHandleValid (PackageList)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
-  //\r
-  // Get the specified package list and image package.\r
-  //\r
-  PackageListNode = NULL;\r
-  for (Link = Private->DatabaseList.ForwardLink;\r
-       Link != &Private->DatabaseList;\r
-       Link = Link->ForwardLink\r
-      ) {\r
-    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
-    if (DatabaseRecord->Handle == PackageList) {\r
-      PackageListNode = DatabaseRecord->PackageList;\r
-      break;\r
-    }\r
-  }\r
+  PackageListNode = LocatePackageList (Database, PackageList);\r
   if (PackageListNode == NULL) {\r
     return EFI_NOT_FOUND;\r
   }\r
@@ -866,27 +863,57 @@ HiiGetImage (
   //\r
   // Find the image block specified by ImageId\r
   //\r
-  LocalImageId = ImageId;\r
-  ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);\r
-  if (ImageBlock == NULL) {\r
+  CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);\r
+  if (CurrentImageBlock == NULL) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  Flag      = FALSE;\r
-  BlockType = *ImageBlock;\r
-\r
-  switch (BlockType) {\r
+  Image->Flags = 0;\r
+  switch (CurrentImageBlock->BlockType) {\r
   case EFI_HII_IIBT_IMAGE_JPEG:\r
+  case EFI_HII_IIBT_IMAGE_PNG:\r
+    if (BitmapOnly) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    ImageOut = NULL;\r
+    Decoder = LocateHiiImageDecoder (CurrentImageBlock->BlockType);\r
+    if (Decoder == NULL) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
     //\r
-    // BUGBUG: need to be supported as soon as image tool is designed.\r
+    // Use the common block code since the definition of two structures is the same.\r
     //\r
-    return EFI_UNSUPPORTED;\r
-    break;\r
+    ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data));\r
+    ASSERT (sizeof (((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Data) ==\r
+            sizeof (((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Data));\r
+    ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Size) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Size));\r
+    ASSERT (sizeof (((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size) ==\r
+            sizeof (((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Size));\r
+    Status = Decoder->DecodeImage (\r
+      Decoder,\r
+      ((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Data,\r
+      ((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size,\r
+      &ImageOut,\r
+      FALSE\r
+    );\r
+\r
+    //\r
+    // Spec requires to use the first capable image decoder instance.\r
+    // The first image decoder instance may fail to decode the image.\r
+    //\r
+    if (!EFI_ERROR (Status)) {\r
+      Image->Bitmap = ImageOut->Image.Bitmap;\r
+      Image->Height = ImageOut->Height;\r
+      Image->Width = ImageOut->Width;\r
+      FreePool (ImageOut);\r
+    }\r
+    return Status;\r
 \r
   case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
   case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
   case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
-    Flag = TRUE;\r
+    Image->Flags = EFI_IMAGE_TRANSPARENT;\r
     //\r
     // fall through\r
     //\r
@@ -896,18 +923,17 @@ HiiGetImage (
     //\r
     // Use the common block code since the definition of these structures is the same.\r
     //\r
-    CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
-    ImageLength = sizeof (EFI_IMAGE_INPUT) + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) *\r
-                  (Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height - 1);\r
-    if (*ImageSize < ImageLength) {\r
-      *ImageSize = ImageLength;\r
-      return EFI_BUFFER_TOO_SMALL;\r
+    CopyMem (&Iibt1bit, CurrentImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
+    ImageLength = (UINTN) Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height;\r
+    if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
     }\r
-    ZeroMem (Image, ImageLength);\r
-\r
-    if (Flag) {\r
-      Image->Flags = EFI_IMAGE_TRANSPARENT;\r
+    ImageLength  *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+    Image->Bitmap = AllocateZeroPool (ImageLength);\r
+    if (Image->Bitmap == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
     }\r
+\r
     Image->Width  = Iibt1bit.Bitmap.Width;\r
     Image->Height = Iibt1bit.Bitmap.Height;\r
 \r
@@ -921,71 +947,100 @@ HiiGetImage (
     //\r
     // Output bitmap data\r
     //\r
-    if (BlockType == EFI_HII_IIBT_IMAGE_1BIT || BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {\r
+    if (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT ||\r
+        CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {\r
       Output1bitPixel (\r
         Image,\r
-        (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8)),\r
+        ((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,\r
         (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
         );\r
-    } else if (BlockType == EFI_HII_IIBT_IMAGE_4BIT || BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {\r
+    } else if (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT ||\r
+               CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {\r
       Output4bitPixel (\r
         Image,\r
-        (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8)),\r
+        ((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,\r
         (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
         );\r
     } else {\r
       Output8bitPixel (\r
         Image,\r
-        (UINT8 *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8)),\r
+        ((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,\r
         (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo\r
         );\r
     }\r
 \r
     return EFI_SUCCESS;\r
-    break;\r
 \r
   case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
-    Flag = TRUE;\r
+    Image->Flags = EFI_IMAGE_TRANSPARENT;\r
     //\r
     // fall through\r
     //\r
   case EFI_HII_IIBT_IMAGE_24BIT:\r
-    CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
-    CopyMem (\r
-      &Height,\r
-      ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
-      sizeof (UINT16)\r
-      );\r
-    ImageLength = sizeof (EFI_IMAGE_INPUT) +\r
-                  sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (Width * Height - 1);\r
-    if (*ImageSize < ImageLength) {\r
-      *ImageSize = ImageLength;\r
-      return EFI_BUFFER_TOO_SMALL;\r
+    Width  = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width);\r
+    Height = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height);\r
+    ImageLength = (UINTN)Width * Height;\r
+    if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
     }\r
-    ZeroMem (Image, ImageLength);\r
-\r
-    if (Flag) {\r
-      Image->Flags = EFI_IMAGE_TRANSPARENT;\r
+    ImageLength  *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+    Image->Bitmap = AllocateZeroPool (ImageLength);\r
+    if (Image->Bitmap == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
     }\r
+\r
     Image->Width  = Width;\r
     Image->Height = Height;\r
 \r
     //\r
-    // Output the bimap data directly.\r
+    // Output the bitmap data directly.\r
     //\r
     Output24bitPixel (\r
       Image,\r
-      (EFI_HII_RGB_PIXEL *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))\r
+      ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Bitmap\r
       );\r
     return EFI_SUCCESS;\r
-    break;\r
 \r
   default:\r
     return EFI_NOT_FOUND;\r
-    break;\r
   }\r
 }\r
 \r
+/**\r
+  This function retrieves the image specified by ImageId which is associated with\r
+  the specified PackageList and copies it into the buffer specified by Image.\r
+\r
+  @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.\r
+  @param  PackageList            Handle of the package list where this image will\r
+                                 be searched.\r
+  @param  ImageId                The image's id,, which is unique within\r
+                                 PackageList.\r
+  @param  Image                  Points to the image.\r
+\r
+  @retval EFI_SUCCESS            The new image was returned successfully.\r
+  @retval EFI_NOT_FOUND           The image specified by ImageId is not in the\r
+                                                database. The specified PackageList is not in the database.\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to\r
+                                 hold the image.\r
+  @retval EFI_INVALID_PARAMETER  The Image or ImageSize was NULL.\r
+  @retval EFI_OUT_OF_RESOURCES   The bitmap could not be retrieved because there was not\r
+                                 enough memory.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetImage (\r
+  IN  CONST EFI_HII_IMAGE_PROTOCOL   *This,\r
+  IN  EFI_HII_HANDLE                 PackageList,\r
+  IN  EFI_IMAGE_ID                   ImageId,\r
+  OUT EFI_IMAGE_INPUT                *Image\r
+  )\r
+{\r
+  HII_DATABASE_PRIVATE_DATA           *Private;\r
+  Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
+  return IGetImage (&Private->DatabaseList, PackageList, ImageId, Image, TRUE);\r
+}\r
+\r
 \r
 /**\r
   This function updates the image specified by ImageId in the specified PackageListHandle to\r
@@ -999,7 +1054,7 @@ HiiGetImage (
 \r
   @retval EFI_SUCCESS            The new image was updated successfully.\r
   @retval EFI_NOT_FOUND          The image specified by ImageId is not in the\r
-                                 database.\r
+                                                database. The specified PackageList is not in the database.\r
   @retval EFI_INVALID_PARAMETER  The Image was NULL.\r
 \r
 **/\r
@@ -1013,53 +1068,22 @@ HiiSetImage (
   )\r
 {\r
   HII_DATABASE_PRIVATE_DATA           *Private;\r
-  LIST_ENTRY                          *Link;\r
-  HII_DATABASE_RECORD                 *DatabaseRecord;\r
   HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
   HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;\r
-  UINT8                               *ImageBlock;\r
-  EFI_IMAGE_ID                        LocalImageId;\r
-  UINT8                               BlockType;\r
-  EFI_HII_IIBT_IMAGE_1BIT_BLOCK       Iibt1bit;\r
-  EFI_HII_IIBT_IMAGE_4BIT_BLOCK       Iibt4bit;\r
-  EFI_HII_IIBT_IMAGE_8BIT_BLOCK       Iibt8bit;\r
-  UINT16                              Width;\r
-  UINT16                              Height;\r
-  UINT32                              BlockSize;\r
+  EFI_HII_IMAGE_BLOCK                 *CurrentImageBlock;\r
+  EFI_HII_IMAGE_BLOCK                 *ImageBlocks;\r
+  EFI_HII_IMAGE_BLOCK                 *NewImageBlock;\r
   UINT32                              NewBlockSize;\r
   UINT32                              OldBlockSize;\r
-  EFI_IMAGE_INPUT                     *ImageIn;\r
-  UINT8                               *NewBlock;\r
-  UINT8                               *NewBlockPtr;\r
-  UINT8                               *Block;\r
-  UINT8                               *BlockPtr;\r
   UINT32                               Part1Size;\r
   UINT32                               Part2Size;\r
 \r
-  if (This == NULL || Image == NULL || ImageId < 1 || PackageList == NULL) {\r
+  if (This == NULL || Image == NULL || ImageId == 0 || Image->Bitmap == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (!IsHiiHandleValid (PackageList)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
   Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
-  //\r
-  // Get the specified package list and image package.\r
-  //\r
-  PackageListNode = NULL;\r
-  for (Link = Private->DatabaseList.ForwardLink;\r
-       Link != &Private->DatabaseList;\r
-       Link = Link->ForwardLink\r
-      ) {\r
-    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
-    if (DatabaseRecord->Handle == PackageList) {\r
-      PackageListNode = DatabaseRecord->PackageList;\r
-      break;\r
-    }\r
-  }\r
+  PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);\r
   if (PackageListNode == NULL) {\r
     return EFI_NOT_FOUND;\r
   }\r
@@ -1071,112 +1095,125 @@ HiiSetImage (
   //\r
   // Find the image block specified by ImageId\r
   //\r
-  LocalImageId = ImageId;\r
-  ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);\r
-  if (ImageBlock == NULL) {\r
+  CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);\r
+  if (CurrentImageBlock == NULL) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  BlockType = *ImageBlock;\r
+  EfiAcquireLock (&mHiiDatabaseLock);\r
 \r
   //\r
   // Get the size of original image block. Use some common block code here\r
   // since the definition of some structures is the same.\r
   //\r
-  switch (BlockType) {\r
+  switch (CurrentImageBlock->BlockType) {\r
   case EFI_HII_IIBT_IMAGE_JPEG:\r
-    //\r
-    // BUGBUG: need to be supported as soon as image tool is designed.\r
-    //\r
-    return EFI_UNSUPPORTED;\r
+    OldBlockSize = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size);\r
+    break;\r
+  case EFI_HII_IIBT_IMAGE_PNG:\r
+    OldBlockSize = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Size);\r
     break;\r
-\r
   case EFI_HII_IIBT_IMAGE_1BIT:\r
   case EFI_HII_IIBT_IMAGE_1BIT_TRANS:\r
-    CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));\r
     OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +\r
-                   BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);\r
+                   BITMAP_LEN_1_BIT (\r
+                     ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),\r
+                     ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)\r
+                     );\r
     break;\r
   case EFI_HII_IIBT_IMAGE_4BIT:\r
   case EFI_HII_IIBT_IMAGE_4BIT_TRANS:\r
-    CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));\r
     OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +\r
-                   BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);\r
+                   BITMAP_LEN_4_BIT (\r
+                     ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),\r
+                     ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)\r
+                     );\r
     break;\r
   case EFI_HII_IIBT_IMAGE_8BIT:\r
   case EFI_HII_IIBT_IMAGE_8BIT_TRANS:\r
-    CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));\r
     OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +\r
-                   BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);\r
+                   BITMAP_LEN_8_BIT (\r
+                     (UINT32) ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),\r
+                     ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)\r
+                     );\r
     break;\r
   case EFI_HII_IIBT_IMAGE_24BIT:\r
   case EFI_HII_IIBT_IMAGE_24BIT_TRANS:\r
-    CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));\r
-    CopyMem (\r
-      &Height,\r
-      ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),\r
-      sizeof (UINT16)\r
-      );\r
     OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
-                   BITMAP_LEN_24_BIT (Width , Height);\r
+                   BITMAP_LEN_24_BIT (\r
+                     (UINT32) ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),\r
+                     ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)\r
+                     );\r
     break;\r
   default:\r
+    EfiReleaseLock (&mHiiDatabaseLock);\r
     return EFI_NOT_FOUND;\r
-    break;\r
   }\r
 \r
   //\r
   // Create the new image block according to input image.\r
   //\r
-  ImageIn = (EFI_IMAGE_INPUT *) Image;\r
-  NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +\r
-                 BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);\r
-  NewBlock = (UINT8 *) AllocateZeroPool (NewBlockSize);\r
-  if (NewBlock == NULL) {\r
+\r
+  //\r
+  // Make sure the final package length doesn't overflow.\r
+  // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.\r
+  // 24Bit BMP occpuies 3 bytes per pixel.\r
+  //\r
+  NewBlockSize = (UINT32)Image->Width * Image->Height;\r
+  if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-\r
-  NewBlockPtr = NewBlock;\r
-  if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
-    *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
-  } else {\r
-    *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT;\r
+  NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));\r
+  if ((NewBlockSize > OldBlockSize) &&\r
+      (NewBlockSize - OldBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length)\r
+      ) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
-  NewBlockPtr++;\r
-\r
-  CopyMem (NewBlockPtr, &ImageIn->Width, sizeof (UINT16));\r
-  NewBlockPtr += sizeof (UINT16);\r
-  CopyMem (NewBlockPtr, &ImageIn->Height, sizeof (UINT16));\r
-  NewBlockPtr += sizeof (UINT16);\r
-\r
-  CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlockPtr, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);\r
 \r
   //\r
   // Adjust the image package to remove the original block firstly then add the new block.\r
   //\r
-  BlockSize = ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize;\r
-  Block = (UINT8 *) AllocateZeroPool (BlockSize);\r
-  if (Block == NULL) {\r
-    SafeFreePool (NewBlock);\r
+  ImageBlocks = AllocateZeroPool (ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize);\r
+  if (ImageBlocks == NULL) {\r
+    EfiReleaseLock (&mHiiDatabaseLock);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  BlockPtr  = Block;\r
-  Part1Size = (UINT32) (ImageBlock - ImagePackage->ImageBlock);\r
+  Part1Size = (UINT32) ((UINTN) CurrentImageBlock - (UINTN) ImagePackage->ImageBlock);\r
   Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;\r
-  CopyMem (BlockPtr, ImagePackage->ImageBlock, Part1Size);\r
-  BlockPtr += Part1Size;\r
-  CopyMem (BlockPtr, NewBlock, NewBlockSize);\r
-  BlockPtr += NewBlockSize;\r
-  CopyMem (BlockPtr, ImageBlock + OldBlockSize, Part2Size);\r
-\r
-  SafeFreePool (ImagePackage->ImageBlock);\r
-  SafeFreePool (NewBlock);\r
-  ImagePackage->ImageBlock     = Block;\r
-  ImagePackage->ImageBlockSize = BlockSize;\r
-  ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;\r
+  CopyMem (ImageBlocks, ImagePackage->ImageBlock, Part1Size);\r
+\r
+  //\r
+  // Set the new image block\r
+  //\r
+  NewImageBlock = (EFI_HII_IMAGE_BLOCK *) ((UINT8 *) ImageBlocks + Part1Size);\r
+  if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
+    NewImageBlock->BlockType= EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
+  } else {\r
+    NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT;\r
+  }\r
+  WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Width, Image->Width);\r
+  WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Height, Image->Height);\r
+  CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Bitmap,\r
+                       Image->Bitmap, (UINT32) Image->Width * Image->Height);\r
+\r
+  CopyMem ((UINT8 *) NewImageBlock + NewBlockSize, (UINT8 *) CurrentImageBlock + OldBlockSize, Part2Size);\r
+\r
+  FreePool (ImagePackage->ImageBlock);\r
+  ImagePackage->ImageBlock                       = ImageBlocks;\r
+  ImagePackage->ImageBlockSize                  += NewBlockSize - OldBlockSize;\r
+  ImagePackage->ImagePkgHdr.Header.Length       += NewBlockSize - OldBlockSize;\r
   PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;\r
 \r
+  //\r
+  // Check whether need to get the contents of HiiDataBase.\r
+  // Only after ReadyToBoot to do the export.\r
+  //\r
+  if (gExportAfterReadyToBoot) {\r
+    HiiGetDatabaseInfo(&Private->HiiDatabase);\r
+  }\r
+\r
+  EfiReleaseLock (&mHiiDatabaseLock);\r
   return EFI_SUCCESS;\r
 \r
 }\r
@@ -1198,6 +1235,8 @@ HiiSetImage (
                                  will be allocated to hold  the generated image and\r
                                  the pointer updated on exit. It is the caller's\r
                                  responsibility to free this buffer.\r
+  @param  BltX                   Specifies the offset from the left and top edge of\r
+                                 the  output image of the first pixel in the image.\r
   @param  BltY                   Specifies the offset from the left and top edge of\r
                                  the  output image of the first pixel in the image.\r
 \r
@@ -1221,19 +1260,17 @@ HiiDrawImage (
   EFI_STATUS                          Status;\r
   HII_DATABASE_PRIVATE_DATA           *Private;\r
   BOOLEAN                             Transparent;\r
-  EFI_IMAGE_INPUT                     *ImageIn;\r
   EFI_IMAGE_OUTPUT                    *ImageOut;\r
   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BltBuffer;\r
   UINTN                               BufferLen;\r
-  UINT                              Width;\r
-  UINT                              Height;\r
-  UINTN                               X;\r
-  UINTN                               Y;\r
+  UINT16                              Width;\r
+  UINT16                              Height;\r
+  UINTN                               Xpos;\r
+  UINTN                               Ypos;\r
   UINTN                               OffsetY1;\r
   UINTN                               OffsetY2;\r
   EFI_FONT_DISPLAY_INFO               *FontInfo;\r
   UINTN                               Index;\r
-  EFI_CONSOLE_CONTROL_PROTOCOL        *Console;\r
 \r
   if (This == NULL || Image == NULL || Blt == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1247,7 +1284,7 @@ HiiDrawImage (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  ImageIn = (EFI_IMAGE_INPUT *) Image;\r
+  FontInfo = NULL;\r
 \r
   //\r
   // Check whether the image will be drawn transparently or opaquely.\r
@@ -1262,7 +1299,7 @@ HiiDrawImage (
     // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending\r
     // on the image's transparency setting.\r
     //\r
-    if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
+    if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
       Transparent = TRUE;\r
     }\r
   }\r
@@ -1287,34 +1324,49 @@ HiiDrawImage (
   // Otherwise a new bitmap will be allocated to hold this image.\r
   //\r
   if (*Blt != NULL) {\r
+    //\r
+    // Make sure the BltX and BltY is inside the Blt area.\r
+    //\r
+    if ((BltX >= (*Blt)->Width) || (BltY >= (*Blt)->Height)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
     //\r
     // Clip the image by (Width, Height)\r
     //\r
 \r
-    Width  = ImageIn->Width;\r
-    Height = ImageIn->Height;\r
+    Width  = Image->Width;\r
+    Height = Image->Height;\r
 \r
-    if (Width > (*Blt)->Width - BltX) {\r
-      Width = (*Blt)->Width - BltX;\r
+    if (Width > (*Blt)->Width - (UINT16)BltX) {\r
+      Width = (*Blt)->Width - (UINT16)BltX;\r
     }\r
-    if (Height > (*Blt)->Height - BltY) {\r
-      Height = (*Blt)->Height - BltY;\r
+    if (Height > (*Blt)->Height - (UINT16)BltY) {\r
+      Height = (*Blt)->Height - (UINT16)BltY;\r
     }\r
 \r
-    BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
-    BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);\r
+    //\r
+    // Prepare the buffer for the temporary image.\r
+    // Make sure the buffer size doesn't overflow UINTN.\r
+    //\r
+    BufferLen = Width * Height;\r
+    if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+    BltBuffer  = AllocateZeroPool (BufferLen);\r
     if (BltBuffer == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
-    if (Width == ImageIn->Width && Height == ImageIn->Height) {\r
-      CopyMem (BltBuffer, ImageIn->Bitmap, BufferLen);\r
+    if (Width == Image->Width && Height == Image->Height) {\r
+      CopyMem (BltBuffer, Image->Bitmap, BufferLen);\r
     } else {\r
-      for (Y = 0; Y < Height; Y++) {\r
-        OffsetY1 = ImageIn->Width * Y;\r
-        OffsetY2 = Width * Y;\r
-        for (X = 0; X < Width; X++) {\r
-          BltBuffer[OffsetY2 + X] = ImageIn->Bitmap[OffsetY1 + X];\r
+      for (Ypos = 0; Ypos < Height; Ypos++) {\r
+        OffsetY1 = Image->Width * Ypos;\r
+        OffsetY2 = Width * Ypos;\r
+        for (Xpos = 0; Xpos < Width; Xpos++) {\r
+          BltBuffer[OffsetY2 + Xpos] = Image->Bitmap[OffsetY1 + Xpos];\r
         }\r
       }\r
     }\r
@@ -1323,17 +1375,10 @@ HiiDrawImage (
     // Draw the image to existing bitmap or screen depending on flag.\r
     //\r
     if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {\r
-      Status = gBS->LocateProtocol (\r
-                      &gEfiConsoleControlProtocolGuid,\r
-                      NULL,\r
-                      (VOID **) &Console\r
-                      );\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
+      //\r
+      // Caller should make sure the current UGA console is grarphic mode.\r
+      //\r
 \r
-      Console->SetMode (Console, EfiConsoleControlScreenGraphics);\r
       //\r
       // Write the image directly to the output device specified by Screen.\r
       //\r
@@ -1365,29 +1410,44 @@ HiiDrawImage (
 \r
     }\r
 \r
-    SafeFreePool (BltBuffer);\r
+    FreePool (BltBuffer);\r
     return Status;\r
 \r
   } else {\r
     //\r
     // Allocate a new bitmap to hold the incoming image.\r
     //\r
-    Width  = ImageIn->Width  + BltX;\r
-    Height = ImageIn->Height + BltY;\r
 \r
-    BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
-    BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);\r
+    //\r
+    // Make sure the final width and height doesn't overflow UINT16.\r
+    //\r
+    if ((BltX > (UINTN)MAX_UINT16 - Image->Width) || (BltY > (UINTN)MAX_UINT16 - Image->Height)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Width  = Image->Width  + (UINT16)BltX;\r
+    Height = Image->Height + (UINT16)BltY;\r
+\r
+    //\r
+    // Make sure the output image size doesn't overflow UINTN.\r
+    //\r
+    BufferLen = Width * Height;\r
+    if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
+    BltBuffer  = AllocateZeroPool (BufferLen);\r
     if (BltBuffer == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
     ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
     if (ImageOut == NULL) {\r
-      SafeFreePool (BltBuffer);\r
+      FreePool (BltBuffer);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
-    ImageOut->Width        = (UINT16) Width;\r
-    ImageOut->Height       = (UINT16) Height;\r
+    ImageOut->Width        = Width;\r
+    ImageOut->Height       = Height;\r
     ImageOut->Image.Bitmap = BltBuffer;\r
 \r
     //\r
@@ -1396,25 +1456,26 @@ HiiDrawImage (
     //\r
     Status = GetSystemFont (Private, &FontInfo, NULL);\r
     if (EFI_ERROR (Status)) {\r
-      SafeFreePool (BltBuffer);\r
-      SafeFreePool (ImageOut);\r
+      FreePool (BltBuffer);\r
+      FreePool (ImageOut);\r
       return Status;\r
     }\r
-    for (Index = 0; Index < Width * Height; Index++) {\r
+    ASSERT (FontInfo != NULL);\r
+    for (Index = 0; Index < (UINTN)Width * Height; Index++) {\r
       BltBuffer[Index] = FontInfo->BackgroundColor;\r
     }\r
-    SafeFreePool (FontInfo);\r
+    FreePool (FontInfo);\r
 \r
     //\r
     // Draw the incoming image to the new created image.\r
     //\r
     *Blt = ImageOut;\r
     return ImageToBlt (\r
-             ImageIn->Bitmap,\r
+             Image->Bitmap,\r
              BltX,\r
              BltY,\r
-             ImageIn->Width,\r
-             ImageIn->Height,\r
+             Image->Width,\r
+             Image->Height,\r
              Transparent,\r
              Blt\r
              );\r
@@ -1443,14 +1504,16 @@ HiiDrawImage (
                                  allocated to hold  the generated image and the\r
                                  pointer updated on exit. It is the caller's\r
                                  responsibility to free this buffer.\r
+  @param  BltX                   Specifies the offset from the left and top edge of\r
+                                 the  output image of the first pixel in the image.\r
   @param  BltY                   Specifies the offset from the left and top edge of\r
                                  the  output image of the first pixel in the image.\r
 \r
   @retval EFI_SUCCESS            The image was successfully drawn.\r
   @retval EFI_OUT_OF_RESOURCES   Unable to allocate an output buffer for Blt.\r
-  @retval EFI_INVALID_PARAMETER  The Image was NULL.\r
-  @retval EFI_NOT_FOUND          The specified packagelist could not be found in\r
-                                 current database.\r
+  @retval EFI_INVALID_PARAMETER  The Blt was NULL.\r
+  @retval EFI_NOT_FOUND          The image specified by ImageId is not in the database.\r
+                           The specified PackageList is not in the database.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1466,44 +1529,30 @@ HiiDrawImageId (
   )\r
 {\r
   EFI_STATUS                          Status;\r
-  EFI_IMAGE_INPUT                     ImageTemp;\r
-  EFI_IMAGE_INPUT                     *Image;\r
-  UINTN                               ImageSize;\r
+  EFI_IMAGE_INPUT                     Image;\r
 \r
   //\r
   // Check input parameter.\r
   //\r
-  if (This == NULL || PackageList == NULL || Blt == NULL || PackageList == NULL) {\r
+  if (This == NULL || Blt == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (!IsHiiHandleValid (PackageList)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
   //\r
   // Get the specified Image.\r
   //\r
-  ImageSize = 0;\r
-  Status = HiiGetImage (This, PackageList, ImageId, &ImageTemp, &ImageSize);\r
-  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+  Status = HiiGetImage (This, PackageList, ImageId, &Image);\r
+  if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  Image = (EFI_IMAGE_INPUT *) AllocateZeroPool (ImageSize);\r
-  if (Image == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  Status = HiiGetImage (This, PackageList, ImageId, Image, &ImageSize);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
   //\r
   // Draw this image.\r
   //\r
-  Status = HiiDrawImage (This, Flags, Image, Blt, BltX, BltY);\r
-  SafeFreePool (Image);\r
+  Status = HiiDrawImage (This, Flags, &Image, Blt, BltX, BltY);\r
+  if (Image.Bitmap != NULL) {\r
+    FreePool (Image.Bitmap);\r
+  }\r
   return Status;\r
 }\r
 \r
-#endif\r
-\r