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