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