]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / Image.c
... / ...
CommitLineData
1/** @file\r
2Implementation for EFI_HII_IMAGE_PROTOCOL.\r
3\r
4\r
5Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>\r
6SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "HiiDatabase.h"\r
11\r
12#define MAX_UINT24 0xFFFFFF\r
13\r
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
18\r
19 This is a internal function.\r
20\r
21 @param ImageBlocks Points to the beginning of a series of image blocks stored in order.\r
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
24\r
25 @return The image block address when input ImageId is not zero; otherwise return NULL.\r
26\r
27**/\r
28EFI_HII_IMAGE_BLOCK *\r
29GetImageIdOrAddress (\r
30 IN EFI_HII_IMAGE_BLOCK *ImageBlocks,\r
31 IN OUT EFI_IMAGE_ID *ImageId\r
32 )\r
33{\r
34 EFI_IMAGE_ID ImageIdCurrent;\r
35 EFI_HII_IMAGE_BLOCK *CurrentImageBlock;\r
36 UINTN Length;\r
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
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
49 if (CurrentImageBlock->BlockType == EFI_HII_IIBT_DUPLICATE) {\r
50 *ImageId = ReadUnaligned16 ((VOID *)&((EFI_HII_IIBT_DUPLICATE_BLOCK *)CurrentImageBlock)->ImageId);\r
51 ASSERT (*ImageId != ImageIdCurrent);\r
52 ASSERT (*ImageId != 0);\r
53 CurrentImageBlock = ImageBlocks;\r
54 ImageIdCurrent = 1;\r
55 continue;\r
56 }\r
57\r
58 return CurrentImageBlock;\r
59 }\r
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
68\r
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
152 }\r
153\r
154 CurrentImageBlock = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)CurrentImageBlock + Length);\r
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
162 return CurrentImageBlock;\r
163 }\r
164\r
165 return NULL;\r
166}\r
167\r
168/**\r
169 Convert pixels from EFI_GRAPHICS_OUTPUT_BLT_PIXEL to EFI_HII_RGB_PIXEL style.\r
170\r
171 This is a internal function.\r
172\r
173\r
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
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
187 UINTN Index;\r
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
196/**\r
197 Convert pixels from EFI_HII_RGB_PIXEL to EFI_GRAPHICS_OUTPUT_BLT_PIXEL style.\r
198\r
199 This is a internal function.\r
200\r
201\r
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
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
215 UINTN Index;\r
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
224/**\r
225 Output pixels in "1 bit per pixel" format to an image.\r
226\r
227 This is a internal function.\r
228\r
229\r
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
238VOID\r
239Output1bitPixel (\r
240 IN OUT EFI_IMAGE_INPUT *Image,\r
241 IN UINT8 *Data,\r
242 IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo\r
243 )\r
244{\r
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
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
262 PaletteSize = 0;\r
263 CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
264 PaletteSize += sizeof (UINT16);\r
265 Palette = AllocateZeroPool (PaletteSize);\r
266 ASSERT (Palette != NULL);\r
267 if (Palette == NULL) {\r
268 return;\r
269 }\r
270\r
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
276 FreePool (Palette);\r
277\r
278 //\r
279 // Convert the pixel from one bit to corresponding color.\r
280 //\r
281 for (Ypos = 0; Ypos < Image->Height; Ypos++) {\r
282 OffsetY = BITMAP_LEN_1_BIT (Image->Width, Ypos);\r
283 //\r
284 // All bits in these bytes are meaningful\r
285 //\r
286 for (Xpos = 0; Xpos < Image->Width / 8; Xpos++) {\r
287 Byte = *(Data + OffsetY + Xpos);\r
288 for (Index = 0; Index < 8; Index++) {\r
289 if ((Byte & (1 << Index)) != 0) {\r
290 BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1];\r
291 } else {\r
292 BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0];\r
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
301 Byte = *(Data + OffsetY + Xpos);\r
302 for (Index = 0; Index < Image->Width % 8; Index++) {\r
303 if ((Byte & (1 << (8 - Index - 1))) != 0) {\r
304 BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1];\r
305 } else {\r
306 BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0];\r
307 }\r
308 }\r
309 }\r
310 }\r
311}\r
312\r
313/**\r
314 Output pixels in "4 bit per pixel" format to an image.\r
315\r
316 This is a internal function.\r
317\r
318\r
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
321 @param[in] PaletteInfo PaletteInfo which stores the color of the output\r
322 pixels. Each entry corresponds to a color within\r
323 [0, 15].\r
324\r
325\r
326**/\r
327VOID\r
328Output4bitPixel (\r
329 IN OUT EFI_IMAGE_INPUT *Image,\r
330 IN UINT8 *Data,\r
331 IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo\r
332 )\r
333{\r
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
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
351 PaletteSize = 0;\r
352 CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
353 PaletteSize += sizeof (UINT16);\r
354 Palette = AllocateZeroPool (PaletteSize);\r
355 ASSERT (Palette != NULL);\r
356 if (Palette == NULL) {\r
357 return;\r
358 }\r
359\r
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
364 CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));\r
365 FreePool (Palette);\r
366\r
367 //\r
368 // Convert the pixel from 4 bit to corresponding color.\r
369 //\r
370 for (Ypos = 0; Ypos < Image->Height; Ypos++) {\r
371 OffsetY = BITMAP_LEN_4_BIT (Image->Width, Ypos);\r
372 //\r
373 // All bits in these bytes are meaningful\r
374 //\r
375 for (Xpos = 0; Xpos < Image->Width / 2; Xpos++) {\r
376 Byte = *(Data + OffsetY + Xpos);\r
377 BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];\r
378 BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1] = PaletteValue[Byte & 0x0F];\r
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
385 Byte = *(Data + OffsetY + Xpos);\r
386 BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];\r
387 }\r
388 }\r
389}\r
390\r
391/**\r
392 Output pixels in "8 bit per pixel" format to an image.\r
393\r
394 This is a internal function.\r
395\r
396\r
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
399 @param[in] PaletteInfo PaletteInfo which stores the color of the output\r
400 pixels. Each entry corresponds to a color within\r
401 [0, 255].\r
402\r
403\r
404**/\r
405VOID\r
406Output8bitPixel (\r
407 IN OUT EFI_IMAGE_INPUT *Image,\r
408 IN UINT8 *Data,\r
409 IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo\r
410 )\r
411{\r
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
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
429 PaletteSize = 0;\r
430 CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));\r
431 PaletteSize += sizeof (UINT16);\r
432 Palette = AllocateZeroPool (PaletteSize);\r
433 ASSERT (Palette != NULL);\r
434 if (Palette == NULL) {\r
435 return;\r
436 }\r
437\r
438 CopyMem (Palette, PaletteInfo, PaletteSize);\r
439 PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));\r
440 ZeroMem (PaletteValue, sizeof (PaletteValue));\r
441 CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));\r
442 FreePool (Palette);\r
443\r
444 //\r
445 // Convert the pixel from 8 bits to corresponding color.\r
446 //\r
447 for (Ypos = 0; Ypos < Image->Height; Ypos++) {\r
448 OffsetY = BITMAP_LEN_8_BIT ((UINT32)Image->Width, Ypos);\r
449 //\r
450 // All bits are meaningful since the bitmap is 8 bits per pixel.\r
451 //\r
452 for (Xpos = 0; Xpos < Image->Width; Xpos++) {\r
453 Byte = *(Data + OffsetY + Xpos);\r
454 BitMapPtr[OffsetY + Xpos] = PaletteValue[Byte];\r
455 }\r
456 }\r
457}\r
458\r
459/**\r
460 Output pixels in "24 bit per pixel" format to an image.\r
461\r
462 This is a internal function.\r
463\r
464\r
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
471VOID\r
472Output24bitPixel (\r
473 IN OUT EFI_IMAGE_INPUT *Image,\r
474 IN EFI_HII_RGB_PIXEL *Data\r
475 )\r
476{\r
477 UINT16 Ypos;\r
478 UINTN OffsetY;\r
479 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;\r
480\r
481 ASSERT (Image != NULL && Data != NULL);\r
482\r
483 BitMapPtr = Image->Bitmap;\r
484\r
485 for (Ypos = 0; Ypos < Image->Height; Ypos++) {\r
486 OffsetY = BITMAP_LEN_8_BIT ((UINT32)Image->Width, Ypos);\r
487 CopyRgbToGopPixel (&BitMapPtr[OffsetY], &Data[OffsetY], Image->Width);\r
488 }\r
489}\r
490\r
491/**\r
492 Convert the image from EFI_IMAGE_INPUT to EFI_IMAGE_OUTPUT format.\r
493\r
494 This is a internal function.\r
495\r
496\r
497 @param BltBuffer Buffer points to bitmap data of incoming image.\r
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
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
513EFI_STATUS\r
514ImageToBlt (\r
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
522 )\r
523{\r
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
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
541\r
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
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
553 if (Transparent) {\r
554 if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {\r
555 ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;\r
556 }\r
557 } else {\r
558 ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;\r
559 }\r
560 }\r
561 }\r
562\r
563 return EFI_SUCCESS;\r
564}\r
565\r
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
576 IN LIST_ENTRY *Database,\r
577 IN EFI_HII_HANDLE PackageList\r
578 )\r
579{\r
580 LIST_ENTRY *Link;\r
581 HII_DATABASE_RECORD *Record;\r
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
589 )\r
590 {\r
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
596\r
597 return NULL;\r
598}\r
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
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
625 )\r
626{\r
627 HII_DATABASE_PRIVATE_DATA *Private;\r
628 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
629 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
630 EFI_HII_IMAGE_BLOCK *ImageBlocks;\r
631 UINT32 NewBlockSize;\r
632\r
633 if ((This == NULL) || (ImageId == NULL) || (Image == NULL) || (Image->Bitmap == NULL)) {\r
634 return EFI_INVALID_PARAMETER;\r
635 }\r
636\r
637 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
638 PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);\r
639 if (PackageListNode == NULL) {\r
640 return EFI_NOT_FOUND;\r
641 }\r
642\r
643 EfiAcquireLock (&mHiiDatabaseLock);\r
644\r
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
652 EfiReleaseLock (&mHiiDatabaseLock);\r
653 return EFI_OUT_OF_RESOURCES;\r
654 }\r
655\r
656 NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));\r
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
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
681 EfiReleaseLock (&mHiiDatabaseLock);\r
682 return EFI_OUT_OF_RESOURCES;\r
683 }\r
684\r
685 //\r
686 // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,\r
687 // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24\r
688 //\r
689 ImageBlocks = AllocatePool (ImagePackage->ImageBlockSize + NewBlockSize);\r
690 if (ImageBlocks == NULL) {\r
691 EfiReleaseLock (&mHiiDatabaseLock);\r
692 return EFI_OUT_OF_RESOURCES;\r
693 }\r
694\r
695 //\r
696 // Copy the original content.\r
697 //\r
698 CopyMem (\r
699 ImageBlocks,\r
700 ImagePackage->ImageBlock,\r
701 ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)\r
702 );\r
703 FreePool (ImagePackage->ImageBlock);\r
704 ImagePackage->ImageBlock = ImageBlocks;\r
705\r
706 //\r
707 // Point to the very last block.\r
708 //\r
709 ImageBlocks = (EFI_HII_IMAGE_BLOCK *)(\r
710 (UINT8 *)ImageBlocks + ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)\r
711 );\r
712 //\r
713 // Update the length record.\r
714 //\r
715 ImagePackage->ImageBlockSize += NewBlockSize;\r
716 ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize;\r
717 PackageListNode->PackageListHdr.PackageLength += NewBlockSize;\r
718 } else {\r
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 EfiReleaseLock (&mHiiDatabaseLock);\r
725 return EFI_OUT_OF_RESOURCES;\r
726 }\r
727\r
728 //\r
729 // The specified package list does not contain image package.\r
730 // Create one to add this image block.\r
731 //\r
732 ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));\r
733 if (ImagePackage == NULL) {\r
734 EfiReleaseLock (&mHiiDatabaseLock);\r
735 return EFI_OUT_OF_RESOURCES;\r
736 }\r
737\r
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
743 //\r
744 // Fill in image package header.\r
745 //\r
746 ImagePackage->ImagePkgHdr.Header.Length = sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);\r
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
760 ImagePackage->ImageBlockSize = NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);\r
761 ImagePackage->ImageBlock = AllocateZeroPool (NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK));\r
762 if (ImagePackage->ImageBlock == NULL) {\r
763 FreePool (ImagePackage);\r
764 EfiReleaseLock (&mHiiDatabaseLock);\r
765 return EFI_OUT_OF_RESOURCES;\r
766 }\r
767\r
768 ImageBlocks = ImagePackage->ImageBlock;\r
769\r
770 //\r
771 // Insert this image package.\r
772 //\r
773 PackageListNode->ImagePkg = ImagePackage;\r
774 PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;\r
775 }\r
776\r
777 //\r
778 // Append the new block here\r
779 //\r
780 if (Image->Flags == EFI_IMAGE_TRANSPARENT) {\r
781 ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
782 } else {\r
783 ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT;\r
784 }\r
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
789\r
790 //\r
791 // Append the block end\r
792 //\r
793 ImageBlocks = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)ImageBlocks + NewBlockSize);\r
794 ImageBlocks->BlockType = EFI_HII_IIBT_END;\r
795\r
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
801 HiiGetDatabaseInfo (&Private->HiiDatabase);\r
802 }\r
803\r
804 EfiReleaseLock (&mHiiDatabaseLock);\r
805\r
806 return EFI_SUCCESS;\r
807}\r
808\r
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
813 @param Database A pointer to the database list header.\r
814 @param PackageList Handle of the package list where this image will\r
815 be searched.\r
816 @param ImageId The image's id,, which is unique within\r
817 PackageList.\r
818 @param Image Points to the image.\r
819 @param BitmapOnly TRUE to only return the bitmap type image.\r
820 FALSE to locate image decoder instance to decode image.\r
821\r
822 @retval EFI_SUCCESS The new image was returned successfully.\r
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
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
828 @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not\r
829 enough memory.\r
830**/\r
831EFI_STATUS\r
832IGetImage (\r
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
838 )\r
839{\r
840 EFI_STATUS Status;\r
841 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
842 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
843 EFI_HII_IMAGE_BLOCK *CurrentImageBlock;\r
844 EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;\r
845 UINT16 Width;\r
846 UINT16 Height;\r
847 UINTN ImageLength;\r
848 UINT8 *PaletteInfo;\r
849 UINT8 PaletteIndex;\r
850 UINT16 PaletteSize;\r
851 EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;\r
852 EFI_IMAGE_OUTPUT *ImageOut;\r
853\r
854 if ((Image == NULL) || (ImageId == 0)) {\r
855 return EFI_INVALID_PARAMETER;\r
856 }\r
857\r
858 PackageListNode = LocatePackageList (Database, PackageList);\r
859 if (PackageListNode == NULL) {\r
860 return EFI_NOT_FOUND;\r
861 }\r
862\r
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
871 CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);\r
872 if (CurrentImageBlock == NULL) {\r
873 return EFI_NOT_FOUND;\r
874 }\r
875\r
876 Image->Flags = 0;\r
877 switch (CurrentImageBlock->BlockType) {\r
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
883\r
884 ImageOut = NULL;\r
885 Decoder = LocateHiiImageDecoder (CurrentImageBlock->BlockType);\r
886 if (Decoder == NULL) {\r
887 return EFI_UNSUPPORTED;\r
888 }\r
889\r
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
923\r
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
928 //\r
929 // fall through\r
930 //\r
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
942\r
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
948\r
949 Image->Width = Iibt1bit.Bitmap.Width;\r
950 Image->Height = Iibt1bit.Bitmap.Height;\r
951\r
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
957\r
958 ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);\r
959\r
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
991 //\r
992 // fall through\r
993 //\r
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
1001\r
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
1007\r
1008 Image->Width = Width;\r
1009 Image->Height = Height;\r
1010\r
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
1022 }\r
1023}\r
1024\r
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
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
1053 )\r
1054{\r
1055 HII_DATABASE_PRIVATE_DATA *Private;\r
1056\r
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
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
1067 @param ImageId The image's id,, which is unique within\r
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
1073 database. The specified PackageList is not in the database.\r
1074 @retval EFI_INVALID_PARAMETER The Image was NULL.\r
1075\r
1076**/\r
1077EFI_STATUS\r
1078EFIAPI\r
1079HiiSetImage (\r
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
1084 )\r
1085{\r
1086 HII_DATABASE_PRIVATE_DATA *Private;\r
1087 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;\r
1088 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;\r
1089 EFI_HII_IMAGE_BLOCK *CurrentImageBlock;\r
1090 EFI_HII_IMAGE_BLOCK *ImageBlocks;\r
1091 EFI_HII_IMAGE_BLOCK *NewImageBlock;\r
1092 UINT32 NewBlockSize;\r
1093 UINT32 OldBlockSize;\r
1094 UINT32 Part1Size;\r
1095 UINT32 Part2Size;\r
1096\r
1097 if ((This == NULL) || (Image == NULL) || (ImageId == 0) || (Image->Bitmap == NULL)) {\r
1098 return EFI_INVALID_PARAMETER;\r
1099 }\r
1100\r
1101 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);\r
1102 PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);\r
1103 if (PackageListNode == NULL) {\r
1104 return EFI_NOT_FOUND;\r
1105 }\r
1106\r
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
1115 CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);\r
1116 if (CurrentImageBlock == NULL) {\r
1117 return EFI_NOT_FOUND;\r
1118 }\r
1119\r
1120 EfiAcquireLock (&mHiiDatabaseLock);\r
1121\r
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
1126 switch (CurrentImageBlock->BlockType) {\r
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
1168 }\r
1169\r
1170 //\r
1171 // Create the new image block according to input image.\r
1172 //\r
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
1181 EfiReleaseLock (&mHiiDatabaseLock);\r
1182 return EFI_OUT_OF_RESOURCES;\r
1183 }\r
1184\r
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
1188 )\r
1189 {\r
1190 EfiReleaseLock (&mHiiDatabaseLock);\r
1191 return EFI_OUT_OF_RESOURCES;\r
1192 }\r
1193\r
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
1199 EfiReleaseLock (&mHiiDatabaseLock);\r
1200 return EFI_OUT_OF_RESOURCES;\r
1201 }\r
1202\r
1203 Part1Size = (UINT32)((UINTN)CurrentImageBlock - (UINTN)ImagePackage->ImageBlock);\r
1204 Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;\r
1205 CopyMem (ImageBlocks, ImagePackage->ImageBlock, Part1Size);\r
1206\r
1207 //\r
1208 // Set the new image block\r
1209 //\r
1210 NewImageBlock = (EFI_HII_IMAGE_BLOCK *)((UINT8 *)ImageBlocks + Part1Size);\r
1211 if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
1212 NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;\r
1213 } else {\r
1214 NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT;\r
1215 }\r
1216\r
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
1226\r
1227 FreePool (ImagePackage->ImageBlock);\r
1228 ImagePackage->ImageBlock = ImageBlocks;\r
1229 ImagePackage->ImageBlockSize += NewBlockSize - OldBlockSize;\r
1230 ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;\r
1231 PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;\r
1232\r
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
1238 HiiGetDatabaseInfo (&Private->HiiDatabase);\r
1239 }\r
1240\r
1241 EfiReleaseLock (&mHiiDatabaseLock);\r
1242 return EFI_SUCCESS;\r
1243}\r
1244\r
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
1259 the pointer updated on exit. It is the caller's\r
1260 responsibility to free this buffer.\r
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
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
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
1281 )\r
1282{\r
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
1299 return EFI_INVALID_PARAMETER;\r
1300 }\r
1301\r
1302 if (((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP) && (*Blt == NULL)) {\r
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
1310 FontInfo = NULL;\r
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
1318 } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE) {\r
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
1325 if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {\r
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
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
1357 //\r
1358 // Clip the image by (Width, Height)\r
1359 //\r
1360\r
1361 Width = Image->Width;\r
1362 Height = Image->Height;\r
1363\r
1364 if (Width > (*Blt)->Width - (UINT16)BltX) {\r
1365 Width = (*Blt)->Width - (UINT16)BltX;\r
1366 }\r
1367\r
1368 if (Height > (*Blt)->Height - (UINT16)BltY) {\r
1369 Height = (*Blt)->Height - (UINT16)BltY;\r
1370 }\r
1371\r
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
1380\r
1381 BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
1382 BltBuffer = AllocateZeroPool (BufferLen);\r
1383 if (BltBuffer == NULL) {\r
1384 return EFI_OUT_OF_RESOURCES;\r
1385 }\r
1386\r
1387 if ((Width == Image->Width) && (Height == Image->Height)) {\r
1388 CopyMem (BltBuffer, Image->Bitmap, BufferLen);\r
1389 } else {\r
1390 for (Ypos = 0; Ypos < Height; Ypos++) {\r
1391 OffsetY1 = Image->Width * Ypos;\r
1392 OffsetY2 = Width * Ypos;\r
1393 for (Xpos = 0; Xpos < Width; Xpos++) {\r
1394 BltBuffer[OffsetY2 + Xpos] = Image->Bitmap[OffsetY1 + Xpos];\r
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
1403 //\r
1404 // Caller should make sure the current UGA console is grarphic mode.\r
1405 //\r
1406\r
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
1435 }\r
1436\r
1437 FreePool (BltBuffer);\r
1438 return Status;\r
1439 } else {\r
1440 //\r
1441 // Allocate a new bitmap to hold the incoming image.\r
1442 //\r
1443\r
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
1461\r
1462 BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);\r
1463 BltBuffer = AllocateZeroPool (BufferLen);\r
1464 if (BltBuffer == NULL) {\r
1465 return EFI_OUT_OF_RESOURCES;\r
1466 }\r
1467\r
1468 ImageOut = (EFI_IMAGE_OUTPUT *)AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));\r
1469 if (ImageOut == NULL) {\r
1470 FreePool (BltBuffer);\r
1471 return EFI_OUT_OF_RESOURCES;\r
1472 }\r
1473\r
1474 ImageOut->Width = Width;\r
1475 ImageOut->Height = Height;\r
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
1484 FreePool (BltBuffer);\r
1485 FreePool (ImageOut);\r
1486 return Status;\r
1487 }\r
1488\r
1489 ASSERT (FontInfo != NULL);\r
1490 for (Index = 0; Index < (UINTN)Width * Height; Index++) {\r
1491 BltBuffer[Index] = FontInfo->BackgroundColor;\r
1492 }\r
1493\r
1494 FreePool (FontInfo);\r
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
1501 Image->Bitmap,\r
1502 BltX,\r
1503 BltY,\r
1504 Image->Width,\r
1505 Image->Height,\r
1506 Transparent,\r
1507 Blt\r
1508 );\r
1509 }\r
1510}\r
1511\r
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
1530 pointer updated on exit. It is the caller's\r
1531 responsibility to free this buffer.\r
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
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
1539 @retval EFI_INVALID_PARAMETER The Blt was NULL.\r
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
1542\r
1543**/\r
1544EFI_STATUS\r
1545EFIAPI\r
1546HiiDrawImageId (\r
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
1554 )\r
1555{\r
1556 EFI_STATUS Status;\r
1557 EFI_IMAGE_INPUT Image;\r
1558\r
1559 //\r
1560 // Check input parameter.\r
1561 //\r
1562 if ((This == NULL) || (Blt == NULL)) {\r
1563 return EFI_INVALID_PARAMETER;\r
1564 }\r
1565\r
1566 //\r
1567 // Get the specified Image.\r
1568 //\r
1569 Status = HiiGetImage (This, PackageList, ImageId, &Image);\r
1570 if (EFI_ERROR (Status)) {\r
1571 return Status;\r
1572 }\r
1573\r
1574 //\r
1575 // Draw this image.\r
1576 //\r
1577 Status = HiiDrawImage (This, Flags, &Image, Blt, BltX, BltY);\r
1578 if (Image.Bitmap != NULL) {\r
1579 FreePool (Image.Bitmap);\r
1580 }\r
1581\r
1582 return Status;\r
1583}\r