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