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