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