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