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 *
GetImageIdOrAddress(IN EFI_HII_IMAGE_BLOCK * ImageBlocks,IN OUT EFI_IMAGE_ID * ImageId)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
CopyGopToRgbPixel(OUT EFI_HII_RGB_PIXEL * BitMapOut,IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BitMapIn,IN UINTN PixelNum)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
CopyRgbToGopPixel(OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL * BitMapOut,IN EFI_HII_RGB_PIXEL * BitMapIn,IN UINTN PixelNum)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
Output1bitPixel(IN OUT EFI_IMAGE_INPUT * Image,IN UINT8 * Data,IN EFI_HII_IMAGE_PALETTE_INFO * PaletteInfo)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
Output4bitPixel(IN OUT EFI_IMAGE_INPUT * Image,IN UINT8 * Data,IN EFI_HII_IMAGE_PALETTE_INFO * PaletteInfo)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
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   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
Output24bitPixel(IN OUT EFI_IMAGE_INPUT * Image,IN EFI_HII_RGB_PIXEL * Data)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
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)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 *
LocatePackageList(IN LIST_ENTRY * Database,IN EFI_HII_HANDLE PackageList)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
HiiNewImage(IN CONST EFI_HII_IMAGE_PROTOCOL * This,IN EFI_HII_HANDLE PackageList,OUT EFI_IMAGE_ID * ImageId,IN CONST EFI_IMAGE_INPUT * Image)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
IGetImage(IN LIST_ENTRY * Database,IN EFI_HII_HANDLE PackageList,IN EFI_IMAGE_ID ImageId,OUT EFI_IMAGE_INPUT * Image,IN BOOLEAN BitmapOnly)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
HiiGetImage(IN CONST EFI_HII_IMAGE_PROTOCOL * This,IN EFI_HII_HANDLE PackageList,IN EFI_IMAGE_ID ImageId,OUT EFI_IMAGE_INPUT * Image)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
HiiSetImage(IN CONST EFI_HII_IMAGE_PROTOCOL * This,IN EFI_HII_HANDLE PackageList,IN EFI_IMAGE_ID ImageId,IN CONST EFI_IMAGE_INPUT * Image)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
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)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
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)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