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