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*
GetImageIdOrAddress(IN UINT8 * ImageBlock,IN OUT EFI_IMAGE_ID * ImageId)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
CopyGopToRgbPixel(OUT EFI_HII_RGB_PIXEL * BitMapOut,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BitMapIn,IN UINTN PixelNum)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
CopyRgbToGopPixel(OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BitMapOut,IN EFI_HII_RGB_PIXEL * BitMapIn,IN UINTN PixelNum)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
Output1bitPixel(IN OUT EFI_IMAGE_INPUT * Image,IN UINT8 * Data,IN EFI_HII_IMAGE_PALETTE_INFO * PaletteInfo)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
Output4bitPixel(IN OUT EFI_IMAGE_INPUT * Image,IN UINT8 * Data,IN EFI_HII_IMAGE_PALETTE_INFO * PaletteInfo)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
Output8bitPixel(IN OUT EFI_IMAGE_INPUT * Image,IN UINT8 * Data,IN EFI_HII_IMAGE_PALETTE_INFO * PaletteInfo)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
Output24bitPixel(IN OUT EFI_IMAGE_INPUT * Image,IN EFI_HII_RGB_PIXEL * Data)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
ImageToBlt(IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BltBuffer,IN UINTN BltX,IN UINTN BltY,IN UINTN Width,IN UINTN Height,IN BOOLEAN Transparent,IN OUT EFI_IMAGE_OUTPUT ** Blt)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
HiiNewImage(IN CONST EFI_HII_IMAGE_PROTOCOL * This,IN EFI_HII_HANDLE PackageList,OUT EFI_IMAGE_ID * ImageId,IN CONST EFI_IMAGE_INPUT * Image)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
HiiGetImage(IN CONST EFI_HII_IMAGE_PROTOCOL * This,IN EFI_HII_HANDLE PackageList,IN EFI_IMAGE_ID ImageId,OUT EFI_IMAGE_INPUT * Image)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
HiiSetImage(IN CONST EFI_HII_IMAGE_PROTOCOL * This,IN EFI_HII_HANDLE PackageList,IN EFI_IMAGE_ID ImageId,IN CONST EFI_IMAGE_INPUT * Image)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
HiiDrawImage(IN CONST EFI_HII_IMAGE_PROTOCOL * This,IN EFI_HII_DRAW_FLAGS Flags,IN CONST EFI_IMAGE_INPUT * Image,IN OUT EFI_IMAGE_OUTPUT ** Blt,IN UINTN BltX,IN UINTN BltY)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
HiiDrawImageId(IN CONST EFI_HII_IMAGE_PROTOCOL * This,IN EFI_HII_DRAW_FLAGS Flags,IN EFI_HII_HANDLE PackageList,IN EFI_IMAGE_ID ImageId,IN OUT EFI_IMAGE_OUTPUT ** Blt,IN UINTN BltX,IN UINTN BltY)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