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