Home | History | Annotate | Download | only in HiiDatabaseDxe
      1 /** @file
      2 Implementation for EFI_HII_IMAGE_PROTOCOL.
      3 
      4 
      5 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 
     17 #include "HiiDatabase.h"
     18 
     19 
     20 /**
     21   Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
     22   ImageId is zero, otherwise return the address of the
     23   corresponding image block with identifier specified by ImageId.
     24 
     25   This is a internal function.
     26 
     27   @param ImageBlock      Points to the beginning of a series of image blocks stored in order.
     28   @param ImageId         If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
     29                          else use this id to find its corresponding image block address.
     30 
     31   @return The image block address when input ImageId is not zero; otherwise return NULL.
     32 
     33 **/
     34 UINT8*
     35 GetImageIdOrAddress (
     36   IN  UINT8           *ImageBlock,
     37   IN OUT EFI_IMAGE_ID *ImageId
     38   )
     39 {
     40   EFI_IMAGE_ID                   ImageIdCurrent;
     41   UINT8                          *ImageBlockHdr;
     42   UINT8                          Length8;
     43   UINT16                         Length16;
     44   UINT32                         Length32;
     45   EFI_HII_IIBT_IMAGE_1BIT_BLOCK  Iibt1bit;
     46   EFI_HII_IIBT_IMAGE_4BIT_BLOCK  Iibt4bit;
     47   EFI_HII_IIBT_IMAGE_8BIT_BLOCK  Iibt8bit;
     48   UINT16                         Width;
     49   UINT16                         Height;
     50 
     51   ASSERT (ImageBlock != NULL && ImageId != NULL);
     52 
     53   ImageBlockHdr  = ImageBlock;
     54   ImageIdCurrent = 1;
     55 
     56   while (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType != EFI_HII_IIBT_END) {
     57     if (*ImageId > 0) {
     58       if (*ImageId == ImageIdCurrent) {
     59         //
     60         // If the found image block is a duplicate block, update the ImageId to
     61         // find the previous defined image block.
     62         //
     63         if (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType == EFI_HII_IIBT_DUPLICATE) {
     64           CopyMem (ImageId, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (EFI_IMAGE_ID));
     65           ASSERT (*ImageId != ImageIdCurrent);
     66           ImageBlock = ImageBlockHdr;
     67           ImageIdCurrent = 1;
     68           continue;
     69         }
     70 
     71         return ImageBlock;
     72       }
     73       if (*ImageId < ImageIdCurrent) {
     74         //
     75         // Can not find the specified image block in this image.
     76         //
     77         return NULL;
     78       }
     79     }
     80     switch (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType) {
     81     case EFI_HII_IIBT_EXT1:
     82       Length8 = *(UINT8*)((UINTN)ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8));
     83       ImageBlock += Length8;
     84       break;
     85     case EFI_HII_IIBT_EXT2:
     86       CopyMem (
     87         &Length16,
     88         (UINT8*)((UINTN)ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8)),
     89         sizeof (UINT16)
     90         );
     91       ImageBlock += Length16;
     92       break;
     93     case EFI_HII_IIBT_EXT4:
     94       CopyMem (
     95         &Length32,
     96         (UINT8*)((UINTN)ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8)),
     97         sizeof (UINT32)
     98         );
     99       ImageBlock += Length32;
    100       break;
    101 
    102     case EFI_HII_IIBT_IMAGE_1BIT:
    103     case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
    104       CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
    105       ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
    106                     BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);
    107       ImageIdCurrent++;
    108       break;
    109 
    110     case EFI_HII_IIBT_IMAGE_4BIT:
    111     case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
    112       CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));
    113       ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
    114                     BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);
    115       ImageIdCurrent++;
    116       break;
    117 
    118     case EFI_HII_IIBT_IMAGE_8BIT:
    119     case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
    120       CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));
    121       ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
    122                     BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);
    123       ImageIdCurrent++;
    124       break;
    125 
    126     case EFI_HII_IIBT_IMAGE_24BIT:
    127     case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
    128       CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
    129       CopyMem (
    130         &Height,
    131         ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
    132         sizeof (UINT16)
    133         );
    134       ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
    135                     BITMAP_LEN_24_BIT (Width, Height);
    136       ImageIdCurrent++;
    137       break;
    138 
    139     case EFI_HII_IIBT_DUPLICATE:
    140       ImageBlock += sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);
    141       ImageIdCurrent++;
    142       break;
    143 
    144     case EFI_HII_IIBT_IMAGE_JPEG:
    145       CopyMem (&Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT32));
    146       ImageBlock += Length32;
    147       ImageIdCurrent++;
    148       break;
    149 
    150     case EFI_HII_IIBT_SKIP1:
    151       Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK));
    152       ImageBlock += sizeof (EFI_HII_IIBT_SKIP1_BLOCK);
    153       ImageIdCurrent = (UINT16) (ImageIdCurrent + Length8);
    154       break;
    155 
    156     case EFI_HII_IIBT_SKIP2:
    157       CopyMem (&Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
    158       ImageBlock += sizeof (EFI_HII_IIBT_SKIP2_BLOCK);
    159       ImageIdCurrent = (UINT16) (ImageIdCurrent + Length16);
    160       break;
    161 
    162     default:
    163       //
    164       // Unknown image blocks can not be skipped, processing halts.
    165       //
    166       ASSERT (FALSE);
    167     }
    168   }
    169 
    170   //
    171   // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK.
    172   //
    173   if (*ImageId == 0) {
    174     *ImageId = ImageIdCurrent;
    175     return ImageBlock;
    176   }
    177 
    178   return NULL;
    179 }
    180 
    181 
    182 
    183 /**
    184   Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.
    185 
    186   This is a internal function.
    187 
    188 
    189   @param  BitMapOut              Pixels in EFI_HII_RGB_PIXEL format.
    190   @param  BitMapIn               Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
    191   @param  PixelNum               The number of pixels to be converted.
    192 
    193 
    194 **/
    195 VOID
    196 CopyGopToRgbPixel (
    197   OUT EFI_HII_RGB_PIXEL              *BitMapOut,
    198   IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BitMapIn,
    199   IN  UINTN                          PixelNum
    200   )
    201 {
    202   UINTN Index;
    203 
    204   ASSERT (BitMapOut != NULL && BitMapIn != NULL);
    205 
    206   for (Index = 0; Index < PixelNum; Index++) {
    207     CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
    208   }
    209 }
    210 
    211 
    212 /**
    213   Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.
    214 
    215   This is a internal function.
    216 
    217 
    218   @param  BitMapOut              Pixels in EFI_GRAPHICS_OUTPUT_BLT_PIXEL format.
    219   @param  BitMapIn               Pixels in EFI_HII_RGB_PIXEL format.
    220   @param  PixelNum               The number of pixels to be converted.
    221 
    222 
    223 **/
    224 VOID
    225 CopyRgbToGopPixel (
    226   OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BitMapOut,
    227   IN  EFI_HII_RGB_PIXEL              *BitMapIn,
    228   IN  UINTN                          PixelNum
    229   )
    230 {
    231   UINTN Index;
    232 
    233   ASSERT (BitMapOut != NULL && BitMapIn != NULL);
    234 
    235   for (Index = 0; Index < PixelNum; Index++) {
    236     CopyMem (BitMapOut + Index, BitMapIn + Index, sizeof (EFI_HII_RGB_PIXEL));
    237   }
    238 }
    239 
    240 
    241 /**
    242   Output pixels in "1 bit per pixel" format to an image.
    243 
    244   This is a internal function.
    245 
    246 
    247   @param  Image                  Points to the image which will store the pixels.
    248   @param  Data                   Stores the value of output pixels, 0 or 1.
    249   @param  PaletteInfo            PaletteInfo which stores the color of the output
    250                                  pixels. First entry corresponds to color 0 and
    251                                  second one to color 1.
    252 
    253 
    254 **/
    255 VOID
    256 Output1bitPixel (
    257   IN OUT EFI_IMAGE_INPUT             *Image,
    258   IN UINT8                           *Data,
    259   IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo
    260   )
    261 {
    262   UINT16                             Xpos;
    263   UINT16                             Ypos;
    264   UINTN                              OffsetY;
    265   UINT8                              Index;
    266   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;
    267   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[2];
    268   EFI_HII_IMAGE_PALETTE_INFO         *Palette;
    269   UINT16                             PaletteSize;
    270   UINT8                              Byte;
    271 
    272   ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
    273 
    274   BitMapPtr = Image->Bitmap;
    275 
    276   //
    277   // First entry corresponds to color 0 and second entry corresponds to color 1.
    278   //
    279   CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
    280   PaletteSize += sizeof (UINT16);
    281   Palette = AllocateZeroPool (PaletteSize);
    282   ASSERT (Palette != NULL);
    283   CopyMem (Palette, PaletteInfo, PaletteSize);
    284 
    285   ZeroMem (PaletteValue, sizeof (PaletteValue));
    286   CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);
    287   CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);
    288   FreePool (Palette);
    289 
    290   //
    291   // Convert the pixel from one bit to corresponding color.
    292   //
    293   for (Ypos = 0; Ypos < Image->Height; Ypos++) {
    294     OffsetY = BITMAP_LEN_1_BIT (Image->Width, Ypos);
    295     //
    296     // All bits in these bytes are meaningful
    297     //
    298     for (Xpos = 0; Xpos < Image->Width / 8; Xpos++) {
    299       Byte = *(Data + OffsetY + Xpos);
    300       for (Index = 0; Index < 8; Index++) {
    301         if ((Byte & (1 << Index)) != 0) {
    302           BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1];
    303         } else {
    304           BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0];
    305         }
    306       }
    307     }
    308 
    309     if (Image->Width % 8 != 0) {
    310       //
    311       // Padding bits in this byte should be ignored.
    312       //
    313       Byte = *(Data + OffsetY + Xpos);
    314       for (Index = 0; Index < Image->Width % 8; Index++) {
    315         if ((Byte & (1 << (8 - Index - 1))) != 0) {
    316           BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1];
    317         } else {
    318           BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0];
    319         }
    320       }
    321     }
    322   }
    323 }
    324 
    325 
    326 /**
    327   Output pixels in "4 bit per pixel" format to an image.
    328 
    329   This is a internal function.
    330 
    331 
    332   @param  Image                  Points to the image which will store the pixels.
    333   @param  Data                   Stores the value of output pixels, 0 ~ 15.
    334   @param[in]  PaletteInfo            PaletteInfo which stores the color of the output
    335                                  pixels. Each entry corresponds to a color within
    336                                  [0, 15].
    337 
    338 
    339 **/
    340 VOID
    341 Output4bitPixel (
    342   IN OUT EFI_IMAGE_INPUT             *Image,
    343   IN UINT8                           *Data,
    344   IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo
    345   )
    346 {
    347   UINT16                             Xpos;
    348   UINT16                             Ypos;
    349   UINTN                              OffsetY;
    350   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;
    351   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[16];
    352   EFI_HII_IMAGE_PALETTE_INFO         *Palette;
    353   UINT16                             PaletteSize;
    354   UINT16                             PaletteNum;
    355   UINT8                              Byte;
    356 
    357   ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
    358 
    359   BitMapPtr = Image->Bitmap;
    360 
    361   //
    362   // The bitmap should allocate each color index starting from 0.
    363   //
    364   CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
    365   PaletteSize += sizeof (UINT16);
    366   Palette = AllocateZeroPool (PaletteSize);
    367   ASSERT (Palette != NULL);
    368   CopyMem (Palette, PaletteInfo, PaletteSize);
    369   PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
    370 
    371   ZeroMem (PaletteValue, sizeof (PaletteValue));
    372   CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);
    373   FreePool (Palette);
    374 
    375   //
    376   // Convert the pixel from 4 bit to corresponding color.
    377   //
    378   for (Ypos = 0; Ypos < Image->Height; Ypos++) {
    379     OffsetY = BITMAP_LEN_4_BIT (Image->Width, Ypos);
    380     //
    381     // All bits in these bytes are meaningful
    382     //
    383     for (Xpos = 0; Xpos < Image->Width / 2; Xpos++) {
    384       Byte = *(Data + OffsetY + Xpos);
    385       BitMapPtr[Ypos * Image->Width + Xpos * 2]     = PaletteValue[Byte >> 4];
    386       BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1] = PaletteValue[Byte & 0x0F];
    387     }
    388 
    389     if (Image->Width % 2 != 0) {
    390       //
    391       // Padding bits in this byte should be ignored.
    392       //
    393       Byte = *(Data + OffsetY + Xpos);
    394       BitMapPtr[Ypos * Image->Width + Xpos * 2]     = PaletteValue[Byte >> 4];
    395     }
    396   }
    397 }
    398 
    399 
    400 /**
    401   Output pixels in "8 bit per pixel" format to an image.
    402 
    403   This is a internal function.
    404 
    405 
    406   @param  Image                  Points to the image which will store the pixels.
    407   @param  Data                   Stores the value of output pixels, 0 ~ 255.
    408   @param[in]  PaletteInfo        PaletteInfo which stores the color of the output
    409                                  pixels. Each entry corresponds to a color within
    410                                  [0, 255].
    411 
    412 
    413 **/
    414 VOID
    415 Output8bitPixel (
    416   IN OUT EFI_IMAGE_INPUT             *Image,
    417   IN UINT8                           *Data,
    418   IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo
    419   )
    420 {
    421   UINT16                             Xpos;
    422   UINT16                             Ypos;
    423   UINTN                              OffsetY;
    424   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;
    425   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[256];
    426   EFI_HII_IMAGE_PALETTE_INFO         *Palette;
    427   UINT16                             PaletteSize;
    428   UINT16                             PaletteNum;
    429   UINT8                              Byte;
    430 
    431   ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
    432 
    433   BitMapPtr = Image->Bitmap;
    434 
    435   //
    436   // The bitmap should allocate each color index starting from 0.
    437   //
    438   CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
    439   PaletteSize += sizeof (UINT16);
    440   Palette = AllocateZeroPool (PaletteSize);
    441   ASSERT (Palette != NULL);
    442   CopyMem (Palette, PaletteInfo, PaletteSize);
    443   PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
    444   ZeroMem (PaletteValue, sizeof (PaletteValue));
    445   CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum);
    446   FreePool (Palette);
    447 
    448   //
    449   // Convert the pixel from 8 bits to corresponding color.
    450   //
    451   for (Ypos = 0; Ypos < Image->Height; Ypos++) {
    452     OffsetY = BITMAP_LEN_8_BIT (Image->Width, Ypos);
    453     //
    454     // All bits are meaningful since the bitmap is 8 bits per pixel.
    455     //
    456     for (Xpos = 0; Xpos < Image->Width; Xpos++) {
    457       Byte = *(Data + OffsetY + Xpos);
    458       BitMapPtr[OffsetY + Xpos] = PaletteValue[Byte];
    459     }
    460   }
    461 
    462 }
    463 
    464 
    465 /**
    466   Output pixels in "24 bit per pixel" format to an image.
    467 
    468   This is a internal function.
    469 
    470 
    471   @param  Image                  Points to the image which will store the pixels.
    472   @param  Data                   Stores the color of output pixels, allowing 16.8
    473                                  millions colors.
    474 
    475 
    476 **/
    477 VOID
    478 Output24bitPixel (
    479   IN OUT EFI_IMAGE_INPUT             *Image,
    480   IN EFI_HII_RGB_PIXEL               *Data
    481   )
    482 {
    483   UINT16                             Ypos;
    484   UINTN                              OffsetY;
    485   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;
    486 
    487   ASSERT (Image != NULL && Data != NULL);
    488 
    489   BitMapPtr = Image->Bitmap;
    490 
    491   for (Ypos = 0; Ypos < Image->Height; Ypos++) {
    492     OffsetY = BITMAP_LEN_8_BIT (Image->Width, Ypos);
    493     CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);
    494   }
    495 
    496 }
    497 
    498 
    499 /**
    500   Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.
    501 
    502   This is a internal function.
    503 
    504 
    505   @param  BltBuffer              Buffer points to bitmap data of incoming image.
    506   @param  BltX                   Specifies the offset from the left and top edge of
    507                                   the output image of the first pixel in the image.
    508   @param  BltY                   Specifies the offset from the left and top edge of
    509                                   the output image of the first pixel in the image.
    510   @param  Width                  Width of the incoming image, in pixels.
    511   @param  Height                 Height of the incoming image, in pixels.
    512   @param  Transparent            If TRUE, all "off" pixels in the image will be
    513                                  drawn using the pixel value from blt and all other
    514                                  pixels will be copied.
    515   @param  Blt                    Buffer points to bitmap data of output image.
    516 
    517   @retval EFI_SUCCESS            The image was successfully converted.
    518   @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.
    519 
    520 **/
    521 EFI_STATUS
    522 ImageToBlt (
    523   IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL   *BltBuffer,
    524   IN UINTN                           BltX,
    525   IN UINTN                           BltY,
    526   IN UINTN                           Width,
    527   IN UINTN                           Height,
    528   IN BOOLEAN                         Transparent,
    529   IN OUT EFI_IMAGE_OUTPUT            **Blt
    530   )
    531 {
    532   EFI_IMAGE_OUTPUT                   *ImageOut;
    533   UINTN                              Xpos;
    534   UINTN                              Ypos;
    535   UINTN                              OffsetY1; // src buffer
    536   UINTN                              OffsetY2; // dest buffer
    537   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      SrcPixel;
    538   EFI_GRAPHICS_OUTPUT_BLT_PIXEL      ZeroPixel;
    539 
    540   if (BltBuffer == NULL || Blt == NULL || *Blt == NULL) {
    541     return EFI_INVALID_PARAMETER;
    542   }
    543 
    544   ImageOut = *Blt;
    545 
    546   if (Width + BltX > ImageOut->Width) {
    547     return EFI_INVALID_PARAMETER;
    548   }
    549   if (Height + BltY > ImageOut->Height) {
    550     return EFI_INVALID_PARAMETER;
    551   }
    552 
    553   ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    554 
    555   for (Ypos = 0; Ypos < Height; Ypos++) {
    556     OffsetY1 = Width * Ypos;
    557     OffsetY2 = ImageOut->Width * (BltY + Ypos);
    558     for (Xpos = 0; Xpos < Width; Xpos++) {
    559       SrcPixel = BltBuffer[OffsetY1 + Xpos];
    560       if (Transparent) {
    561         if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {
    562           ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
    563         }
    564       } else {
    565         ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
    566       }
    567     }
    568   }
    569 
    570   return EFI_SUCCESS;
    571 }
    572 
    573 
    574 /**
    575   This function adds the image Image to the group of images owned by PackageList, and returns
    576   a new image identifier (ImageId).
    577 
    578   @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
    579   @param  PackageList            Handle of the package list where this image will
    580                                  be added.
    581   @param  ImageId                On return, contains the new image id, which is
    582                                  unique within PackageList.
    583   @param  Image                  Points to the image.
    584 
    585   @retval EFI_SUCCESS            The new image was added successfully.
    586   @retval EFI_NOT_FOUND          The specified PackageList could not be found in
    587                                  database.
    588   @retval EFI_OUT_OF_RESOURCES   Could not add the image due to lack of resources.
    589   @retval EFI_INVALID_PARAMETER  Image is NULL or ImageId is NULL.
    590 
    591 **/
    592 EFI_STATUS
    593 EFIAPI
    594 HiiNewImage (
    595   IN  CONST EFI_HII_IMAGE_PROTOCOL   *This,
    596   IN  EFI_HII_HANDLE                 PackageList,
    597   OUT EFI_IMAGE_ID                   *ImageId,
    598   IN  CONST EFI_IMAGE_INPUT          *Image
    599   )
    600 {
    601   HII_DATABASE_PRIVATE_DATA           *Private;
    602   LIST_ENTRY                          *Link;
    603   HII_DATABASE_RECORD                 *DatabaseRecord;
    604   HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;
    605   HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;
    606   UINT8                               *ImageBlock;
    607   UINTN                               BlockSize;
    608   UINT8                               *NewBlock;
    609   UINT8                               *NewBlockPtr;
    610   UINTN                               NewBlockSize;
    611   EFI_IMAGE_INPUT                     *ImageIn;
    612 
    613   if (This == NULL || ImageId == NULL || Image == NULL || Image->Bitmap == NULL) {
    614     return EFI_INVALID_PARAMETER;
    615   }
    616 
    617   if (!IsHiiHandleValid (PackageList)) {
    618     return EFI_NOT_FOUND;
    619   }
    620 
    621   Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
    622 
    623   //
    624   // Get the specified package list
    625   //
    626 
    627   PackageListNode = NULL;
    628 
    629   for (Link = Private->DatabaseList.ForwardLink;
    630        Link != &Private->DatabaseList;
    631        Link = Link->ForwardLink
    632       ) {
    633     DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
    634     if (DatabaseRecord->Handle == PackageList) {
    635       PackageListNode = DatabaseRecord->PackageList;
    636       break;
    637     }
    638   }
    639 
    640   if (PackageListNode == NULL) {
    641     return EFI_NOT_FOUND;
    642   }
    643 
    644   ImageIn = (EFI_IMAGE_INPUT *) Image;
    645 
    646   NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
    647                  BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);
    648 
    649   //
    650   // Get the image package in the package list,
    651   // or create a new image package if image package does not exist.
    652   //
    653   if (PackageListNode->ImagePkg != NULL) {
    654     ImagePackage = PackageListNode->ImagePkg;
    655 
    656     //
    657     // Output the image id of the incoming image being inserted, which is the
    658     // image id of the EFI_HII_IIBT_END block of old image package.
    659     //
    660     *ImageId = 0;
    661     GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);
    662 
    663     //
    664     // Update the package's image block by appending the new block to the end.
    665     //
    666     BlockSize  = ImagePackage->ImageBlockSize + NewBlockSize;
    667     ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);
    668     if (ImageBlock == NULL) {
    669       return EFI_OUT_OF_RESOURCES;
    670     }
    671     //
    672     // Copy the original content.
    673     //
    674     CopyMem (
    675       ImageBlock,
    676       ImagePackage->ImageBlock,
    677       ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
    678       );
    679     FreePool (ImagePackage->ImageBlock);
    680     ImagePackage->ImageBlock = ImageBlock;
    681     ImageBlock += ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK);
    682     //
    683     // Temp memory to store new block.
    684     //
    685     NewBlock = AllocateZeroPool (NewBlockSize);
    686     if (NewBlock == NULL) {
    687       FreePool (ImagePackage->ImageBlock);
    688       return EFI_OUT_OF_RESOURCES;
    689     }
    690     NewBlockPtr = NewBlock;
    691 
    692     //
    693     // Update the length record.
    694     //
    695     ImagePackage->ImageBlockSize = (UINT32) BlockSize;
    696     ImagePackage->ImagePkgHdr.Header.Length += (UINT32) NewBlockSize;
    697     PackageListNode->PackageListHdr.PackageLength += (UINT32) NewBlockSize;
    698 
    699   } else {
    700     //
    701     // The specified package list does not contain image package.
    702     // Create one to add this image block.
    703     //
    704     ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
    705     if (ImagePackage == NULL) {
    706       return EFI_OUT_OF_RESOURCES;
    707     }
    708     //
    709     // Output the image id of the incoming image being inserted, which is the
    710     // first image block so that id is initially to one.
    711     //
    712     *ImageId = 1;
    713     BlockSize    = sizeof (EFI_HII_IIBT_END_BLOCK) + NewBlockSize;
    714     //
    715     // Fill in image package header.
    716     //
    717     ImagePackage->ImagePkgHdr.Header.Length     = (UINT32) BlockSize + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
    718     ImagePackage->ImagePkgHdr.Header.Type       = EFI_HII_PACKAGE_IMAGES;
    719     ImagePackage->ImagePkgHdr.ImageInfoOffset   = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
    720     ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;
    721 
    722     //
    723     // Fill in palette info.
    724     //
    725     ImagePackage->PaletteBlock    = NULL;
    726     ImagePackage->PaletteInfoSize = 0;
    727 
    728     //
    729     // Fill in image blocks.
    730     //
    731     ImagePackage->ImageBlockSize = (UINT32) BlockSize;
    732     ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);
    733     if (ImagePackage->ImageBlock == NULL) {
    734       FreePool (ImagePackage);
    735       return EFI_OUT_OF_RESOURCES;
    736     }
    737     ImageBlock = ImagePackage->ImageBlock;
    738 
    739     //
    740     // Temp memory to store new block.
    741     //
    742     NewBlock = AllocateZeroPool (NewBlockSize);
    743     if (NewBlock == NULL) {
    744       FreePool (ImagePackage->ImageBlock);
    745       FreePool (ImagePackage);
    746       return EFI_OUT_OF_RESOURCES;
    747     }
    748     NewBlockPtr = NewBlock;
    749 
    750     //
    751     // Insert this image package.
    752     //
    753     PackageListNode->ImagePkg = ImagePackage;
    754     PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
    755   }
    756 
    757   //
    758   // Append the new block here
    759   //
    760   if (ImageIn->Flags == EFI_IMAGE_TRANSPARENT) {
    761     *NewBlock = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
    762   } else {
    763     *NewBlock = EFI_HII_IIBT_IMAGE_24BIT;
    764   }
    765   NewBlock++;
    766   CopyMem (NewBlock, &ImageIn->Width, sizeof (UINT16));
    767   NewBlock += sizeof (UINT16);
    768   CopyMem (NewBlock, &ImageIn->Height, sizeof (UINT16));
    769   NewBlock += sizeof (UINT16);
    770   CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlock, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);
    771 
    772   CopyMem (ImageBlock, NewBlockPtr, NewBlockSize);
    773   FreePool (NewBlockPtr);
    774 
    775   //
    776   // Append the block end
    777   //
    778   ImageBlock += NewBlockSize;
    779   ((EFI_HII_IIBT_END_BLOCK *) (ImageBlock))->Header.BlockType = EFI_HII_IIBT_END;
    780 
    781   return EFI_SUCCESS;
    782 }
    783 
    784 
    785 /**
    786   This function retrieves the image specified by ImageId which is associated with
    787   the specified PackageList and copies it into the buffer specified by Image.
    788 
    789   @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
    790   @param  PackageList            Handle of the package list where this image will
    791                                  be searched.
    792   @param  ImageId                The image's id,, which is unique within
    793                                  PackageList.
    794   @param  Image                  Points to the image.
    795 
    796   @retval EFI_SUCCESS            The new image was returned successfully.
    797   @retval EFI_NOT_FOUND           The image specified by ImageId is not in the
    798                                                 database. The specified PackageList is not in the database.
    799   @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to
    800                                  hold the image.
    801   @retval EFI_INVALID_PARAMETER  The Image or ImageSize was NULL.
    802   @retval EFI_OUT_OF_RESOURCES   The bitmap could not be retrieved because there was not
    803                                                      enough memory.
    804 
    805 **/
    806 EFI_STATUS
    807 EFIAPI
    808 HiiGetImage (
    809   IN  CONST EFI_HII_IMAGE_PROTOCOL   *This,
    810   IN  EFI_HII_HANDLE                 PackageList,
    811   IN  EFI_IMAGE_ID                   ImageId,
    812   OUT EFI_IMAGE_INPUT                *Image
    813   )
    814 {
    815   HII_DATABASE_PRIVATE_DATA           *Private;
    816   LIST_ENTRY                          *Link;
    817   HII_DATABASE_RECORD                 *DatabaseRecord;
    818   HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;
    819   HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;
    820   UINT8                               *ImageBlock;
    821   EFI_IMAGE_ID                        LocalImageId;
    822   UINT8                               BlockType;
    823   EFI_HII_IIBT_IMAGE_1BIT_BLOCK       Iibt1bit;
    824   UINT16                              Width;
    825   UINT16                              Height;
    826   UINTN                               ImageLength;
    827   BOOLEAN                             Flag;
    828   UINT8                               *PaletteInfo;
    829   UINT8                               PaletteIndex;
    830   UINT16                              PaletteSize;
    831 
    832   if (This == NULL || Image == NULL || ImageId < 1) {
    833     return EFI_INVALID_PARAMETER;
    834   }
    835 
    836   if (!IsHiiHandleValid (PackageList)) {
    837     return EFI_NOT_FOUND;
    838   }
    839 
    840   Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
    841 
    842   //
    843   // Get the specified package list and image package.
    844   //
    845   PackageListNode = NULL;
    846   for (Link = Private->DatabaseList.ForwardLink;
    847        Link != &Private->DatabaseList;
    848        Link = Link->ForwardLink
    849       ) {
    850     DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
    851     if (DatabaseRecord->Handle == PackageList) {
    852       PackageListNode = DatabaseRecord->PackageList;
    853       break;
    854     }
    855   }
    856   if (PackageListNode == NULL) {
    857     return EFI_NOT_FOUND;
    858   }
    859   ImagePackage = PackageListNode->ImagePkg;
    860   if (ImagePackage == NULL) {
    861     return EFI_NOT_FOUND;
    862   }
    863 
    864   //
    865   // Find the image block specified by ImageId
    866   //
    867   LocalImageId = ImageId;
    868   ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);
    869   if (ImageBlock == NULL) {
    870     return EFI_NOT_FOUND;
    871   }
    872 
    873   Flag      = FALSE;
    874   BlockType = *ImageBlock;
    875 
    876   switch (BlockType) {
    877   case EFI_HII_IIBT_IMAGE_JPEG:
    878     //
    879     // BUGBUG: need to be supported as soon as image tool is designed.
    880     //
    881     return EFI_UNSUPPORTED;
    882 
    883   case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
    884   case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
    885   case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
    886     Flag = TRUE;
    887     //
    888     // fall through
    889     //
    890   case EFI_HII_IIBT_IMAGE_1BIT:
    891   case EFI_HII_IIBT_IMAGE_4BIT:
    892   case EFI_HII_IIBT_IMAGE_8BIT:
    893     //
    894     // Use the common block code since the definition of these structures is the same.
    895     //
    896     CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
    897     ImageLength = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) *
    898                   (Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height);
    899     Image->Bitmap = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (ImageLength);
    900     if (Image->Bitmap == NULL) {
    901       return EFI_OUT_OF_RESOURCES;
    902     }
    903 
    904     if (Flag) {
    905       Image->Flags = EFI_IMAGE_TRANSPARENT;
    906     }
    907     Image->Width  = Iibt1bit.Bitmap.Width;
    908     Image->Height = Iibt1bit.Bitmap.Height;
    909 
    910     PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
    911     for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {
    912       CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
    913       PaletteInfo += PaletteSize + sizeof (UINT16);
    914     }
    915     ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);
    916 
    917     //
    918     // Output bitmap data
    919     //
    920     if (BlockType == EFI_HII_IIBT_IMAGE_1BIT || BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {
    921       Output1bitPixel (
    922         Image,
    923         (UINT8 *) ((UINTN)ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8)),
    924         (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
    925         );
    926     } else if (BlockType == EFI_HII_IIBT_IMAGE_4BIT || BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {
    927       Output4bitPixel (
    928         Image,
    929         (UINT8 *) ((UINTN)ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8)),
    930         (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
    931         );
    932     } else {
    933       Output8bitPixel (
    934         Image,
    935         (UINT8 *) ((UINTN)ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8)),
    936         (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
    937         );
    938     }
    939 
    940     return EFI_SUCCESS;
    941 
    942   case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
    943     Flag = TRUE;
    944     //
    945     // fall through
    946     //
    947   case EFI_HII_IIBT_IMAGE_24BIT:
    948     CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
    949     CopyMem (
    950       &Height,
    951       ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
    952       sizeof (UINT16)
    953       );
    954     ImageLength = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (Width * Height);
    955     Image->Bitmap = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (ImageLength);
    956     if (Image->Bitmap == NULL) {
    957       return EFI_OUT_OF_RESOURCES;
    958     }
    959 
    960     if (Flag) {
    961       Image->Flags = EFI_IMAGE_TRANSPARENT;
    962     }
    963     Image->Width  = Width;
    964     Image->Height = Height;
    965 
    966     //
    967     // Output the bimap data directly.
    968     //
    969     Output24bitPixel (
    970       Image,
    971       (EFI_HII_RGB_PIXEL *) (ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))
    972       );
    973     return EFI_SUCCESS;
    974 
    975   default:
    976     return EFI_NOT_FOUND;
    977   }
    978 }
    979 
    980 
    981 /**
    982   This function updates the image specified by ImageId in the specified PackageListHandle to
    983   the image specified by Image.
    984 
    985   @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
    986   @param  PackageList            The package list containing the images.
    987   @param  ImageId                The image's id,, which is unique within
    988                                  PackageList.
    989   @param  Image                  Points to the image.
    990 
    991   @retval EFI_SUCCESS            The new image was updated successfully.
    992   @retval EFI_NOT_FOUND          The image specified by ImageId is not in the
    993                                                 database. The specified PackageList is not in the database.
    994   @retval EFI_INVALID_PARAMETER  The Image was NULL.
    995 
    996 **/
    997 EFI_STATUS
    998 EFIAPI
    999 HiiSetImage (
   1000   IN CONST EFI_HII_IMAGE_PROTOCOL    *This,
   1001   IN EFI_HII_HANDLE                  PackageList,
   1002   IN EFI_IMAGE_ID                    ImageId,
   1003   IN CONST EFI_IMAGE_INPUT           *Image
   1004   )
   1005 {
   1006   HII_DATABASE_PRIVATE_DATA           *Private;
   1007   LIST_ENTRY                          *Link;
   1008   HII_DATABASE_RECORD                 *DatabaseRecord;
   1009   HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;
   1010   HII_IMAGE_PACKAGE_INSTANCE          *ImagePackage;
   1011   UINT8                               *ImageBlock;
   1012   EFI_IMAGE_ID                        LocalImageId;
   1013   UINT8                               BlockType;
   1014   EFI_HII_IIBT_IMAGE_1BIT_BLOCK       Iibt1bit;
   1015   EFI_HII_IIBT_IMAGE_4BIT_BLOCK       Iibt4bit;
   1016   EFI_HII_IIBT_IMAGE_8BIT_BLOCK       Iibt8bit;
   1017   UINT16                              Width;
   1018   UINT16                              Height;
   1019   UINT32                              BlockSize;
   1020   UINT32                              NewBlockSize;
   1021   UINT32                              OldBlockSize;
   1022   EFI_IMAGE_INPUT                     *ImageIn;
   1023   UINT8                               *NewBlock;
   1024   UINT8                               *NewBlockPtr;
   1025   UINT8                               *Block;
   1026   UINT8                               *BlockPtr;
   1027   UINT32                               Part1Size;
   1028   UINT32                               Part2Size;
   1029 
   1030   if (This == NULL || Image == NULL || ImageId < 1 || Image->Bitmap == NULL) {
   1031     return EFI_INVALID_PARAMETER;
   1032   }
   1033 
   1034   if (!IsHiiHandleValid (PackageList)) {
   1035     return EFI_NOT_FOUND;
   1036   }
   1037 
   1038   Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   1039 
   1040   //
   1041   // Get the specified package list and image package.
   1042   //
   1043   PackageListNode = NULL;
   1044   for (Link = Private->DatabaseList.ForwardLink;
   1045        Link != &Private->DatabaseList;
   1046        Link = Link->ForwardLink
   1047       ) {
   1048     DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
   1049     if (DatabaseRecord->Handle == PackageList) {
   1050       PackageListNode = DatabaseRecord->PackageList;
   1051       break;
   1052     }
   1053   }
   1054   if (PackageListNode == NULL) {
   1055     return EFI_NOT_FOUND;
   1056   }
   1057   ImagePackage = PackageListNode->ImagePkg;
   1058   if (ImagePackage == NULL) {
   1059     return EFI_NOT_FOUND;
   1060   }
   1061 
   1062   //
   1063   // Find the image block specified by ImageId
   1064   //
   1065   LocalImageId = ImageId;
   1066   ImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);
   1067   if (ImageBlock == NULL) {
   1068     return EFI_NOT_FOUND;
   1069   }
   1070 
   1071   BlockType = *ImageBlock;
   1072 
   1073   //
   1074   // Get the size of original image block. Use some common block code here
   1075   // since the definition of some structures is the same.
   1076   //
   1077   switch (BlockType) {
   1078   case EFI_HII_IIBT_IMAGE_JPEG:
   1079     //
   1080     // BUGBUG: need to be supported as soon as image tool is designed.
   1081     //
   1082     return EFI_UNSUPPORTED;
   1083 
   1084   case EFI_HII_IIBT_IMAGE_1BIT:
   1085   case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
   1086     CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
   1087     OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
   1088                    BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);
   1089     break;
   1090   case EFI_HII_IIBT_IMAGE_4BIT:
   1091   case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
   1092     CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));
   1093     OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
   1094                    BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);
   1095     break;
   1096   case EFI_HII_IIBT_IMAGE_8BIT:
   1097   case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
   1098     CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));
   1099     OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
   1100                    BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);
   1101     break;
   1102   case EFI_HII_IIBT_IMAGE_24BIT:
   1103   case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
   1104     CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
   1105     CopyMem (
   1106       &Height,
   1107       ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
   1108       sizeof (UINT16)
   1109       );
   1110     OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
   1111                    BITMAP_LEN_24_BIT (Width , Height);
   1112     break;
   1113   default:
   1114     return EFI_NOT_FOUND;
   1115   }
   1116 
   1117   //
   1118   // Create the new image block according to input image.
   1119   //
   1120   ImageIn = (EFI_IMAGE_INPUT *) Image;
   1121   NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
   1122                  BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);
   1123   NewBlock = (UINT8 *) AllocateZeroPool (NewBlockSize);
   1124   if (NewBlock == NULL) {
   1125     return EFI_OUT_OF_RESOURCES;
   1126   }
   1127 
   1128   NewBlockPtr = NewBlock;
   1129   if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
   1130     *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
   1131   } else {
   1132     *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT;
   1133   }
   1134   NewBlockPtr++;
   1135 
   1136   CopyMem (NewBlockPtr, &ImageIn->Width, sizeof (UINT16));
   1137   NewBlockPtr += sizeof (UINT16);
   1138   CopyMem (NewBlockPtr, &ImageIn->Height, sizeof (UINT16));
   1139   NewBlockPtr += sizeof (UINT16);
   1140 
   1141   CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlockPtr, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);
   1142 
   1143   //
   1144   // Adjust the image package to remove the original block firstly then add the new block.
   1145   //
   1146   BlockSize = ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize;
   1147   Block = (UINT8 *) AllocateZeroPool (BlockSize);
   1148   if (Block == NULL) {
   1149     FreePool (NewBlock);
   1150     return EFI_OUT_OF_RESOURCES;
   1151   }
   1152 
   1153   BlockPtr  = Block;
   1154   Part1Size = (UINT32) (ImageBlock - ImagePackage->ImageBlock);
   1155   Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;
   1156   CopyMem (BlockPtr, ImagePackage->ImageBlock, Part1Size);
   1157   BlockPtr += Part1Size;
   1158   CopyMem (BlockPtr, NewBlock, NewBlockSize);
   1159   BlockPtr += NewBlockSize;
   1160   CopyMem (BlockPtr, ImageBlock + OldBlockSize, Part2Size);
   1161 
   1162   FreePool (ImagePackage->ImageBlock);
   1163   FreePool (NewBlock);
   1164   ImagePackage->ImageBlock     = Block;
   1165   ImagePackage->ImageBlockSize = BlockSize;
   1166   ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;
   1167   PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;
   1168 
   1169   return EFI_SUCCESS;
   1170 
   1171 }
   1172 
   1173 
   1174 /**
   1175   This function renders an image to a bitmap or the screen using the specified
   1176   color and options. It draws the image on an existing bitmap, allocates a new
   1177   bitmap or uses the screen. The images can be clipped.
   1178 
   1179   @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
   1180   @param  Flags                  Describes how the image is to be drawn.
   1181   @param  Image                  Points to the image to be displayed.
   1182   @param  Blt                    If this points to a non-NULL on entry, this points
   1183                                  to the image, which is Width pixels wide and
   1184                                  Height pixels high.  The image will be drawn onto
   1185                                  this image and  EFI_HII_DRAW_FLAG_CLIP is implied.
   1186                                  If this points to a  NULL on entry, then a buffer
   1187                                  will be allocated to hold  the generated image and
   1188                                  the pointer updated on exit. It is the caller's
   1189                                  responsibility to free this buffer.
   1190   @param  BltX                   Specifies the offset from the left and top edge of
   1191                                  the  output image of the first pixel in the image.
   1192   @param  BltY                   Specifies the offset from the left and top edge of
   1193                                  the  output image of the first pixel in the image.
   1194 
   1195   @retval EFI_SUCCESS            The image was successfully drawn.
   1196   @retval EFI_OUT_OF_RESOURCES   Unable to allocate an output buffer for Blt.
   1197   @retval EFI_INVALID_PARAMETER  The Image or Blt was NULL.
   1198   @retval EFI_INVALID_PARAMETER  Any combination of Flags is invalid.
   1199 
   1200 **/
   1201 EFI_STATUS
   1202 EFIAPI
   1203 HiiDrawImage (
   1204   IN CONST EFI_HII_IMAGE_PROTOCOL    *This,
   1205   IN EFI_HII_DRAW_FLAGS              Flags,
   1206   IN CONST EFI_IMAGE_INPUT           *Image,
   1207   IN OUT EFI_IMAGE_OUTPUT            **Blt,
   1208   IN UINTN                           BltX,
   1209   IN UINTN                           BltY
   1210   )
   1211 {
   1212   EFI_STATUS                          Status;
   1213   HII_DATABASE_PRIVATE_DATA           *Private;
   1214   BOOLEAN                             Transparent;
   1215   EFI_IMAGE_INPUT                     *ImageIn;
   1216   EFI_IMAGE_OUTPUT                    *ImageOut;
   1217   EFI_GRAPHICS_OUTPUT_BLT_PIXEL       *BltBuffer;
   1218   UINTN                               BufferLen;
   1219   UINTN                               Width;
   1220   UINTN                               Height;
   1221   UINTN                               Xpos;
   1222   UINTN                               Ypos;
   1223   UINTN                               OffsetY1;
   1224   UINTN                               OffsetY2;
   1225   EFI_FONT_DISPLAY_INFO               *FontInfo;
   1226   UINTN                               Index;
   1227 
   1228   if (This == NULL || Image == NULL || Blt == NULL) {
   1229     return EFI_INVALID_PARAMETER;
   1230   }
   1231 
   1232   if ((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP && *Blt == NULL) {
   1233     return EFI_INVALID_PARAMETER;
   1234   }
   1235 
   1236   if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {
   1237     return EFI_INVALID_PARAMETER;
   1238   }
   1239 
   1240   FontInfo = NULL;
   1241   ImageIn = (EFI_IMAGE_INPUT *) Image;
   1242 
   1243   //
   1244   // Check whether the image will be drawn transparently or opaquely.
   1245   //
   1246   Transparent = FALSE;
   1247   if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {
   1248     Transparent = TRUE;
   1249   } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE){
   1250     Transparent = FALSE;
   1251   } else {
   1252     //
   1253     // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
   1254     // on the image's transparency setting.
   1255     //
   1256     if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
   1257       Transparent = TRUE;
   1258     }
   1259   }
   1260 
   1261   //
   1262   // Image cannot be drawn transparently if Blt points to NULL on entry.
   1263   // Currently output to Screen transparently is not supported, either.
   1264   //
   1265   if (Transparent) {
   1266     if (*Blt == NULL) {
   1267       return EFI_INVALID_PARAMETER;
   1268     } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
   1269       return EFI_INVALID_PARAMETER;
   1270     }
   1271   }
   1272 
   1273   Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
   1274 
   1275   //
   1276   // When Blt points to a non-NULL on entry, this image will be drawn onto
   1277   // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
   1278   // Otherwise a new bitmap will be allocated to hold this image.
   1279   //
   1280   if (*Blt != NULL) {
   1281     //
   1282     // Clip the image by (Width, Height)
   1283     //
   1284 
   1285     Width  = ImageIn->Width;
   1286     Height = ImageIn->Height;
   1287 
   1288     if (Width > (*Blt)->Width - BltX) {
   1289       Width = (*Blt)->Width - BltX;
   1290     }
   1291     if (Height > (*Blt)->Height - BltY) {
   1292       Height = (*Blt)->Height - BltY;
   1293     }
   1294 
   1295     BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
   1296     BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
   1297     if (BltBuffer == NULL) {
   1298       return EFI_OUT_OF_RESOURCES;
   1299     }
   1300 
   1301     if (Width == ImageIn->Width && Height == ImageIn->Height) {
   1302       CopyMem (BltBuffer, ImageIn->Bitmap, BufferLen);
   1303     } else {
   1304       for (Ypos = 0; Ypos < Height; Ypos++) {
   1305         OffsetY1 = ImageIn->Width * Ypos;
   1306         OffsetY2 = Width * Ypos;
   1307         for (Xpos = 0; Xpos < Width; Xpos++) {
   1308           BltBuffer[OffsetY2 + Xpos] = ImageIn->Bitmap[OffsetY1 + Xpos];
   1309         }
   1310       }
   1311     }
   1312 
   1313     //
   1314     // Draw the image to existing bitmap or screen depending on flag.
   1315     //
   1316     if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
   1317       //
   1318       // Caller should make sure the current UGA console is grarphic mode.
   1319       //
   1320 
   1321       //
   1322       // Write the image directly to the output device specified by Screen.
   1323       //
   1324       Status = (*Blt)->Image.Screen->Blt (
   1325                                        (*Blt)->Image.Screen,
   1326                                        BltBuffer,
   1327                                        EfiBltBufferToVideo,
   1328                                        0,
   1329                                        0,
   1330                                        BltX,
   1331                                        BltY,
   1332                                        Width,
   1333                                        Height,
   1334                                        0
   1335                                        );
   1336     } else {
   1337       //
   1338       // Draw the image onto the existing bitmap specified by Bitmap.
   1339       //
   1340       Status = ImageToBlt (
   1341                  BltBuffer,
   1342                  BltX,
   1343                  BltY,
   1344                  Width,
   1345                  Height,
   1346                  Transparent,
   1347                  Blt
   1348                  );
   1349 
   1350     }
   1351 
   1352     FreePool (BltBuffer);
   1353     return Status;
   1354 
   1355   } else {
   1356     //
   1357     // Allocate a new bitmap to hold the incoming image.
   1358     //
   1359     Width  = ImageIn->Width  + BltX;
   1360     Height = ImageIn->Height + BltY;
   1361 
   1362     BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
   1363     BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
   1364     if (BltBuffer == NULL) {
   1365       return EFI_OUT_OF_RESOURCES;
   1366     }
   1367 
   1368     ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
   1369     if (ImageOut == NULL) {
   1370       FreePool (BltBuffer);
   1371       return EFI_OUT_OF_RESOURCES;
   1372     }
   1373     ImageOut->Width        = (UINT16) Width;
   1374     ImageOut->Height       = (UINT16) Height;
   1375     ImageOut->Image.Bitmap = BltBuffer;
   1376 
   1377     //
   1378     // BUGBUG: Now all the "blank" pixels are filled with system default background
   1379     // color. Not sure if it need to be updated or not.
   1380     //
   1381     Status = GetSystemFont (Private, &FontInfo, NULL);
   1382     if (EFI_ERROR (Status)) {
   1383       FreePool (BltBuffer);
   1384       FreePool (ImageOut);
   1385       return Status;
   1386     }
   1387     ASSERT (FontInfo != NULL);
   1388     for (Index = 0; Index < Width * Height; Index++) {
   1389       BltBuffer[Index] = FontInfo->BackgroundColor;
   1390     }
   1391     FreePool (FontInfo);
   1392 
   1393     //
   1394     // Draw the incoming image to the new created image.
   1395     //
   1396     *Blt = ImageOut;
   1397     return ImageToBlt (
   1398              ImageIn->Bitmap,
   1399              BltX,
   1400              BltY,
   1401              ImageIn->Width,
   1402              ImageIn->Height,
   1403              Transparent,
   1404              Blt
   1405              );
   1406 
   1407   }
   1408 }
   1409 
   1410 
   1411 /**
   1412   This function renders an image to a bitmap or the screen using the specified
   1413   color and options. It draws the image on an existing bitmap, allocates a new
   1414   bitmap or uses the screen. The images can be clipped.
   1415 
   1416   @param  This                   A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
   1417   @param  Flags                  Describes how the image is to be drawn.
   1418   @param  PackageList            The package list in the HII database to search for
   1419                                  the  specified image.
   1420   @param  ImageId                The image's id, which is unique within
   1421                                  PackageList.
   1422   @param  Blt                    If this points to a non-NULL on entry, this points
   1423                                  to the image, which is Width pixels wide and
   1424                                  Height pixels high. The image will be drawn onto
   1425                                  this image and
   1426                                  EFI_HII_DRAW_FLAG_CLIP is implied. If this points
   1427                                  to a  NULL on entry, then a buffer will be
   1428                                  allocated to hold  the generated image and the
   1429                                  pointer updated on exit. It is the caller's
   1430                                  responsibility to free this buffer.
   1431   @param  BltX                   Specifies the offset from the left and top edge of
   1432                                  the  output image of the first pixel in the image.
   1433   @param  BltY                   Specifies the offset from the left and top edge of
   1434                                  the  output image of the first pixel in the image.
   1435 
   1436   @retval EFI_SUCCESS            The image was successfully drawn.
   1437   @retval EFI_OUT_OF_RESOURCES   Unable to allocate an output buffer for Blt.
   1438   @retval EFI_INVALID_PARAMETER  The Blt was NULL.
   1439   @retval EFI_NOT_FOUND          The image specified by ImageId is not in the database.
   1440                            The specified PackageList is not in the database.
   1441 
   1442 **/
   1443 EFI_STATUS
   1444 EFIAPI
   1445 HiiDrawImageId (
   1446   IN CONST EFI_HII_IMAGE_PROTOCOL    *This,
   1447   IN EFI_HII_DRAW_FLAGS              Flags,
   1448   IN EFI_HII_HANDLE                  PackageList,
   1449   IN EFI_IMAGE_ID                    ImageId,
   1450   IN OUT EFI_IMAGE_OUTPUT            **Blt,
   1451   IN UINTN                           BltX,
   1452   IN UINTN                           BltY
   1453   )
   1454 {
   1455   EFI_STATUS                          Status;
   1456   EFI_IMAGE_INPUT                     Image;
   1457 
   1458   //
   1459   // Check input parameter.
   1460   //
   1461   if (This == NULL || Blt == NULL) {
   1462     return EFI_INVALID_PARAMETER;
   1463   }
   1464 
   1465   if (!IsHiiHandleValid (PackageList)) {
   1466     return EFI_NOT_FOUND;
   1467   }
   1468 
   1469   //
   1470   // Get the specified Image.
   1471   //
   1472   Status = HiiGetImage (This, PackageList, ImageId, &Image);
   1473   if (EFI_ERROR (Status)) {
   1474     return Status;
   1475   }
   1476 
   1477   //
   1478   // Draw this image.
   1479   //
   1480   Status = HiiDrawImage (This, Flags, &Image, Blt, BltX, BltY);
   1481   if (Image.Bitmap != NULL) {
   1482     FreePool (Image.Bitmap);
   1483   }
   1484   return Status;
   1485 }
   1486 
   1487