]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / Image.c
1 /** @file
2 Implementation for EFI_HII_IMAGE_PROTOCOL.
3
4
5 Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10
11 #include "HiiDatabase.h"
12
13 #define MAX_UINT24 0xFFFFFF
14
15 /**
16 Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input
17 ImageId is zero, otherwise return the address of the
18 corresponding image block with identifier specified by ImageId.
19
20 This is a internal function.
21
22 @param ImageBlocks Points to the beginning of a series of image blocks stored in order.
23 @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK;
24 else use this id to find its corresponding image block address.
25
26 @return The image block address when input ImageId is not zero; otherwise return NULL.
27
28 **/
29 EFI_HII_IMAGE_BLOCK *
30 GetImageIdOrAddress (
31 IN EFI_HII_IMAGE_BLOCK *ImageBlocks,
32 IN OUT EFI_IMAGE_ID *ImageId
33 )
34 {
35 EFI_IMAGE_ID ImageIdCurrent;
36 EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
37 UINTN Length;
38
39 ASSERT (ImageBlocks != NULL && ImageId != NULL);
40 CurrentImageBlock = ImageBlocks;
41 ImageIdCurrent = 1;
42
43 while (CurrentImageBlock->BlockType != EFI_HII_IIBT_END) {
44 if (*ImageId != 0) {
45 if (*ImageId == ImageIdCurrent) {
46 //
47 // If the found image block is a duplicate block, update the ImageId to
48 // find the previous defined image block.
49 //
50 if (CurrentImageBlock->BlockType == EFI_HII_IIBT_DUPLICATE) {
51 *ImageId = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_DUPLICATE_BLOCK *) CurrentImageBlock)->ImageId);
52 ASSERT (*ImageId != ImageIdCurrent);
53 ASSERT (*ImageId != 0);
54 CurrentImageBlock = ImageBlocks;
55 ImageIdCurrent = 1;
56 continue;
57 }
58
59 return CurrentImageBlock;
60 }
61 if (*ImageId < ImageIdCurrent) {
62 //
63 // Can not find the specified image block in this image.
64 //
65 return NULL;
66 }
67 }
68 switch (CurrentImageBlock->BlockType) {
69 case EFI_HII_IIBT_EXT1:
70 Length = ((EFI_HII_IIBT_EXT1_BLOCK *) CurrentImageBlock)->Length;
71 break;
72 case EFI_HII_IIBT_EXT2:
73 Length = ReadUnaligned16 (&((EFI_HII_IIBT_EXT2_BLOCK *) CurrentImageBlock)->Length);
74 break;
75 case EFI_HII_IIBT_EXT4:
76 Length = ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_EXT4_BLOCK *) CurrentImageBlock)->Length);
77 break;
78
79 case EFI_HII_IIBT_IMAGE_1BIT:
80 case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
81 Length = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
82 BITMAP_LEN_1_BIT (
83 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
84 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
85 );
86 ImageIdCurrent++;
87 break;
88
89 case EFI_HII_IIBT_IMAGE_4BIT:
90 case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
91 Length = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
92 BITMAP_LEN_4_BIT (
93 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
94 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
95 );
96 ImageIdCurrent++;
97 break;
98
99 case EFI_HII_IIBT_IMAGE_8BIT:
100 case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
101 Length = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
102 BITMAP_LEN_8_BIT (
103 (UINT32) ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
104 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
105 );
106 ImageIdCurrent++;
107 break;
108
109 case EFI_HII_IIBT_IMAGE_24BIT:
110 case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
111 Length = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
112 BITMAP_LEN_24_BIT (
113 (UINT32) ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
114 ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
115 );
116 ImageIdCurrent++;
117 break;
118
119 case EFI_HII_IIBT_DUPLICATE:
120 Length = sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK);
121 ImageIdCurrent++;
122 break;
123
124 case EFI_HII_IIBT_IMAGE_JPEG:
125 Length = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size);
126 ImageIdCurrent++;
127 break;
128
129 case EFI_HII_IIBT_IMAGE_PNG:
130 Length = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_PNG_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, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
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, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
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 ((UINT32) 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 ((UINT32) 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 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
642 PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
643 if (PackageListNode == NULL) {
644 return EFI_NOT_FOUND;
645 }
646
647 EfiAcquireLock (&mHiiDatabaseLock);
648
649 //
650 // Calcuate the size of new image.
651 // Make sure the size doesn't overflow UINT32.
652 // Note: 24Bit BMP occpuies 3 bytes per pixel.
653 //
654 NewBlockSize = (UINT32)Image->Width * Image->Height;
655 if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
656 EfiReleaseLock (&mHiiDatabaseLock);
657 return EFI_OUT_OF_RESOURCES;
658 }
659 NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
660
661 //
662 // Get the image package in the package list,
663 // or create a new image package if image package does not exist.
664 //
665 if (PackageListNode->ImagePkg != NULL) {
666 ImagePackage = PackageListNode->ImagePkg;
667
668 //
669 // Output the image id of the incoming image being inserted, which is the
670 // image id of the EFI_HII_IIBT_END block of old image package.
671 //
672 *ImageId = 0;
673 GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);
674
675 //
676 // Update the package's image block by appending the new block to the end.
677 //
678
679 //
680 // Make sure the final package length doesn't overflow.
681 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
682 //
683 if (NewBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length) {
684 EfiReleaseLock (&mHiiDatabaseLock);
685 return EFI_OUT_OF_RESOURCES;
686 }
687 //
688 // Because ImagePackage->ImageBlockSize < ImagePackage->ImagePkgHdr.Header.Length,
689 // So (ImagePackage->ImageBlockSize + NewBlockSize) <= MAX_UINT24
690 //
691 ImageBlocks = AllocatePool (ImagePackage->ImageBlockSize + NewBlockSize);
692 if (ImageBlocks == NULL) {
693 EfiReleaseLock (&mHiiDatabaseLock);
694 return EFI_OUT_OF_RESOURCES;
695 }
696 //
697 // Copy the original content.
698 //
699 CopyMem (
700 ImageBlocks,
701 ImagePackage->ImageBlock,
702 ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
703 );
704 FreePool (ImagePackage->ImageBlock);
705 ImagePackage->ImageBlock = ImageBlocks;
706
707 //
708 // Point to the very last block.
709 //
710 ImageBlocks = (EFI_HII_IMAGE_BLOCK *) (
711 (UINT8 *) ImageBlocks + ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
712 );
713 //
714 // Update the length record.
715 //
716 ImagePackage->ImageBlockSize += NewBlockSize;
717 ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize;
718 PackageListNode->PackageListHdr.PackageLength += NewBlockSize;
719
720 } else {
721 //
722 // Make sure the final package length doesn't overflow.
723 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
724 //
725 if (NewBlockSize > MAX_UINT24 - (sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + sizeof (EFI_HII_IIBT_END_BLOCK))) {
726 EfiReleaseLock (&mHiiDatabaseLock);
727 return EFI_OUT_OF_RESOURCES;
728 }
729 //
730 // The specified package list does not contain image package.
731 // Create one to add this image block.
732 //
733 ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
734 if (ImagePackage == NULL) {
735 EfiReleaseLock (&mHiiDatabaseLock);
736 return EFI_OUT_OF_RESOURCES;
737 }
738 //
739 // Output the image id of the incoming image being inserted, which is the
740 // first image block so that id is initially to one.
741 //
742 *ImageId = 1;
743 //
744 // Fill in image package header.
745 //
746 ImagePackage->ImagePkgHdr.Header.Length = sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);
747 ImagePackage->ImagePkgHdr.Header.Type = EFI_HII_PACKAGE_IMAGES;
748 ImagePackage->ImagePkgHdr.ImageInfoOffset = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
749 ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;
750
751 //
752 // Fill in palette info.
753 //
754 ImagePackage->PaletteBlock = NULL;
755 ImagePackage->PaletteInfoSize = 0;
756
757 //
758 // Fill in image blocks.
759 //
760 ImagePackage->ImageBlockSize = NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK);
761 ImagePackage->ImageBlock = AllocateZeroPool (NewBlockSize + sizeof (EFI_HII_IIBT_END_BLOCK));
762 if (ImagePackage->ImageBlock == NULL) {
763 FreePool (ImagePackage);
764 EfiReleaseLock (&mHiiDatabaseLock);
765 return EFI_OUT_OF_RESOURCES;
766 }
767 ImageBlocks = ImagePackage->ImageBlock;
768
769 //
770 // Insert this image package.
771 //
772 PackageListNode->ImagePkg = ImagePackage;
773 PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
774 }
775
776 //
777 // Append the new block here
778 //
779 if (Image->Flags == EFI_IMAGE_TRANSPARENT) {
780 ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
781 } else {
782 ImageBlocks->BlockType = EFI_HII_IIBT_IMAGE_24BIT;
783 }
784 WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Width, Image->Width);
785 WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Height, Image->Height);
786 CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) ImageBlocks)->Bitmap.Bitmap, Image->Bitmap, (UINT32) Image->Width * Image->Height);
787
788 //
789 // Append the block end
790 //
791 ImageBlocks = (EFI_HII_IMAGE_BLOCK *) ((UINT8 *) ImageBlocks + NewBlockSize);
792 ImageBlocks->BlockType = EFI_HII_IIBT_END;
793
794 //
795 // Check whether need to get the contents of HiiDataBase.
796 // Only after ReadyToBoot to do the export.
797 //
798 if (gExportAfterReadyToBoot) {
799 HiiGetDatabaseInfo(&Private->HiiDatabase);
800 }
801
802 EfiReleaseLock (&mHiiDatabaseLock);
803
804 return EFI_SUCCESS;
805 }
806
807
808 /**
809 This function retrieves the image specified by ImageId which is associated with
810 the specified PackageList and copies it into the buffer specified by Image.
811
812 @param Database A pointer to the database list header.
813 @param PackageList Handle of the package list where this image will
814 be searched.
815 @param ImageId The image's id,, which is unique within
816 PackageList.
817 @param Image Points to the image.
818 @param BitmapOnly TRUE to only return the bitmap type image.
819 FALSE to locate image decoder instance to decode image.
820
821 @retval EFI_SUCCESS The new image was returned successfully.
822 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
823 database. The specified PackageList is not in the database.
824 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
825 hold the image.
826 @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
827 @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
828 enough memory.
829 **/
830 EFI_STATUS
831 IGetImage (
832 IN LIST_ENTRY *Database,
833 IN EFI_HII_HANDLE PackageList,
834 IN EFI_IMAGE_ID ImageId,
835 OUT EFI_IMAGE_INPUT *Image,
836 IN BOOLEAN BitmapOnly
837 )
838 {
839 EFI_STATUS Status;
840 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
841 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
842 EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
843 EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
844 UINT16 Width;
845 UINT16 Height;
846 UINTN ImageLength;
847 UINT8 *PaletteInfo;
848 UINT8 PaletteIndex;
849 UINT16 PaletteSize;
850 EFI_HII_IMAGE_DECODER_PROTOCOL *Decoder;
851 EFI_IMAGE_OUTPUT *ImageOut;
852
853 if (Image == NULL || ImageId == 0) {
854 return EFI_INVALID_PARAMETER;
855 }
856
857 PackageListNode = LocatePackageList (Database, PackageList);
858 if (PackageListNode == NULL) {
859 return EFI_NOT_FOUND;
860 }
861 ImagePackage = PackageListNode->ImagePkg;
862 if (ImagePackage == NULL) {
863 return EFI_NOT_FOUND;
864 }
865
866 //
867 // Find the image block specified by ImageId
868 //
869 CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
870 if (CurrentImageBlock == NULL) {
871 return EFI_NOT_FOUND;
872 }
873
874 Image->Flags = 0;
875 switch (CurrentImageBlock->BlockType) {
876 case EFI_HII_IIBT_IMAGE_JPEG:
877 case EFI_HII_IIBT_IMAGE_PNG:
878 if (BitmapOnly) {
879 return EFI_UNSUPPORTED;
880 }
881
882 ImageOut = NULL;
883 Decoder = LocateHiiImageDecoder (CurrentImageBlock->BlockType);
884 if (Decoder == NULL) {
885 return EFI_UNSUPPORTED;
886 }
887 //
888 // Use the common block code since the definition of two structures is the same.
889 //
890 ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data));
891 ASSERT (sizeof (((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Data) ==
892 sizeof (((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Data));
893 ASSERT (OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Size) == OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Size));
894 ASSERT (sizeof (((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size) ==
895 sizeof (((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Size));
896 Status = Decoder->DecodeImage (
897 Decoder,
898 ((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Data,
899 ((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size,
900 &ImageOut,
901 FALSE
902 );
903
904 //
905 // Spec requires to use the first capable image decoder instance.
906 // The first image decoder instance may fail to decode the image.
907 //
908 if (!EFI_ERROR (Status)) {
909 Image->Bitmap = ImageOut->Image.Bitmap;
910 Image->Height = ImageOut->Height;
911 Image->Width = ImageOut->Width;
912 FreePool (ImageOut);
913 }
914 return Status;
915
916 case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
917 case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
918 case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
919 Image->Flags = EFI_IMAGE_TRANSPARENT;
920 //
921 // fall through
922 //
923 case EFI_HII_IIBT_IMAGE_1BIT:
924 case EFI_HII_IIBT_IMAGE_4BIT:
925 case EFI_HII_IIBT_IMAGE_8BIT:
926 //
927 // Use the common block code since the definition of these structures is the same.
928 //
929 CopyMem (&Iibt1bit, CurrentImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
930 ImageLength = (UINTN) Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height;
931 if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
932 return EFI_OUT_OF_RESOURCES;
933 }
934 ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
935 Image->Bitmap = AllocateZeroPool (ImageLength);
936 if (Image->Bitmap == NULL) {
937 return EFI_OUT_OF_RESOURCES;
938 }
939
940 Image->Width = Iibt1bit.Bitmap.Width;
941 Image->Height = Iibt1bit.Bitmap.Height;
942
943 PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
944 for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {
945 CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
946 PaletteInfo += PaletteSize + sizeof (UINT16);
947 }
948 ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);
949
950 //
951 // Output bitmap data
952 //
953 if (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT ||
954 CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {
955 Output1bitPixel (
956 Image,
957 ((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,
958 (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
959 );
960 } else if (CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT ||
961 CurrentImageBlock->BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {
962 Output4bitPixel (
963 Image,
964 ((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,
965 (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
966 );
967 } else {
968 Output8bitPixel (
969 Image,
970 ((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Data,
971 (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
972 );
973 }
974
975 return EFI_SUCCESS;
976
977 case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
978 Image->Flags = EFI_IMAGE_TRANSPARENT;
979 //
980 // fall through
981 //
982 case EFI_HII_IIBT_IMAGE_24BIT:
983 Width = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width);
984 Height = ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height);
985 ImageLength = (UINTN)Width * Height;
986 if (ImageLength > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
987 return EFI_OUT_OF_RESOURCES;
988 }
989 ImageLength *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
990 Image->Bitmap = AllocateZeroPool (ImageLength);
991 if (Image->Bitmap == NULL) {
992 return EFI_OUT_OF_RESOURCES;
993 }
994
995 Image->Width = Width;
996 Image->Height = Height;
997
998 //
999 // Output the bitmap data directly.
1000 //
1001 Output24bitPixel (
1002 Image,
1003 ((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Bitmap
1004 );
1005 return EFI_SUCCESS;
1006
1007 default:
1008 return EFI_NOT_FOUND;
1009 }
1010 }
1011
1012 /**
1013 This function retrieves the image specified by ImageId which is associated with
1014 the specified PackageList and copies it into the buffer specified by Image.
1015
1016 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1017 @param PackageList Handle of the package list where this image will
1018 be searched.
1019 @param ImageId The image's id,, which is unique within
1020 PackageList.
1021 @param Image Points to the image.
1022
1023 @retval EFI_SUCCESS The new image was returned successfully.
1024 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
1025 database. The specified PackageList is not in the database.
1026 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
1027 hold the image.
1028 @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
1029 @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
1030 enough memory.
1031
1032 **/
1033 EFI_STATUS
1034 EFIAPI
1035 HiiGetImage (
1036 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
1037 IN EFI_HII_HANDLE PackageList,
1038 IN EFI_IMAGE_ID ImageId,
1039 OUT EFI_IMAGE_INPUT *Image
1040 )
1041 {
1042 HII_DATABASE_PRIVATE_DATA *Private;
1043 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1044 return IGetImage (&Private->DatabaseList, PackageList, ImageId, Image, TRUE);
1045 }
1046
1047
1048 /**
1049 This function updates the image specified by ImageId in the specified PackageListHandle to
1050 the image specified by Image.
1051
1052 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1053 @param PackageList The package list containing the images.
1054 @param ImageId The image's id,, which is unique within
1055 PackageList.
1056 @param Image Points to the image.
1057
1058 @retval EFI_SUCCESS The new image was updated successfully.
1059 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
1060 database. The specified PackageList is not in the database.
1061 @retval EFI_INVALID_PARAMETER The Image was NULL.
1062
1063 **/
1064 EFI_STATUS
1065 EFIAPI
1066 HiiSetImage (
1067 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
1068 IN EFI_HII_HANDLE PackageList,
1069 IN EFI_IMAGE_ID ImageId,
1070 IN CONST EFI_IMAGE_INPUT *Image
1071 )
1072 {
1073 HII_DATABASE_PRIVATE_DATA *Private;
1074 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1075 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
1076 EFI_HII_IMAGE_BLOCK *CurrentImageBlock;
1077 EFI_HII_IMAGE_BLOCK *ImageBlocks;
1078 EFI_HII_IMAGE_BLOCK *NewImageBlock;
1079 UINT32 NewBlockSize;
1080 UINT32 OldBlockSize;
1081 UINT32 Part1Size;
1082 UINT32 Part2Size;
1083
1084 if (This == NULL || Image == NULL || ImageId == 0 || Image->Bitmap == NULL) {
1085 return EFI_INVALID_PARAMETER;
1086 }
1087
1088 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1089 PackageListNode = LocatePackageList (&Private->DatabaseList, PackageList);
1090 if (PackageListNode == NULL) {
1091 return EFI_NOT_FOUND;
1092 }
1093 ImagePackage = PackageListNode->ImagePkg;
1094 if (ImagePackage == NULL) {
1095 return EFI_NOT_FOUND;
1096 }
1097
1098 //
1099 // Find the image block specified by ImageId
1100 //
1101 CurrentImageBlock = GetImageIdOrAddress (ImagePackage->ImageBlock, &ImageId);
1102 if (CurrentImageBlock == NULL) {
1103 return EFI_NOT_FOUND;
1104 }
1105
1106 EfiAcquireLock (&mHiiDatabaseLock);
1107
1108 //
1109 // Get the size of original image block. Use some common block code here
1110 // since the definition of some structures is the same.
1111 //
1112 switch (CurrentImageBlock->BlockType) {
1113 case EFI_HII_IIBT_IMAGE_JPEG:
1114 OldBlockSize = OFFSET_OF (EFI_HII_IIBT_JPEG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_JPEG_BLOCK *) CurrentImageBlock)->Size);
1115 break;
1116 case EFI_HII_IIBT_IMAGE_PNG:
1117 OldBlockSize = OFFSET_OF (EFI_HII_IIBT_PNG_BLOCK, Data) + ReadUnaligned32 ((VOID *) &((EFI_HII_IIBT_PNG_BLOCK *) CurrentImageBlock)->Size);
1118 break;
1119 case EFI_HII_IIBT_IMAGE_1BIT:
1120 case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
1121 OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
1122 BITMAP_LEN_1_BIT (
1123 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
1124 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_1BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
1125 );
1126 break;
1127 case EFI_HII_IIBT_IMAGE_4BIT:
1128 case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
1129 OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
1130 BITMAP_LEN_4_BIT (
1131 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
1132 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_4BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
1133 );
1134 break;
1135 case EFI_HII_IIBT_IMAGE_8BIT:
1136 case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
1137 OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
1138 BITMAP_LEN_8_BIT (
1139 (UINT32) ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
1140 ReadUnaligned16 (&((EFI_HII_IIBT_IMAGE_8BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
1141 );
1142 break;
1143 case EFI_HII_IIBT_IMAGE_24BIT:
1144 case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
1145 OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
1146 BITMAP_LEN_24_BIT (
1147 (UINT32) ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Width),
1148 ReadUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) CurrentImageBlock)->Bitmap.Height)
1149 );
1150 break;
1151 default:
1152 EfiReleaseLock (&mHiiDatabaseLock);
1153 return EFI_NOT_FOUND;
1154 }
1155
1156 //
1157 // Create the new image block according to input image.
1158 //
1159
1160 //
1161 // Make sure the final package length doesn't overflow.
1162 // Length of the package header is represented using 24 bits. So MAX length is MAX_UINT24.
1163 // 24Bit BMP occpuies 3 bytes per pixel.
1164 //
1165 NewBlockSize = (UINT32)Image->Width * Image->Height;
1166 if (NewBlockSize > (MAX_UINT32 - (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL))) / 3) {
1167 EfiReleaseLock (&mHiiDatabaseLock);
1168 return EFI_OUT_OF_RESOURCES;
1169 }
1170 NewBlockSize = NewBlockSize * 3 + (sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL));
1171 if ((NewBlockSize > OldBlockSize) &&
1172 (NewBlockSize - OldBlockSize > MAX_UINT24 - ImagePackage->ImagePkgHdr.Header.Length)
1173 ) {
1174 EfiReleaseLock (&mHiiDatabaseLock);
1175 return EFI_OUT_OF_RESOURCES;
1176 }
1177
1178 //
1179 // Adjust the image package to remove the original block firstly then add the new block.
1180 //
1181 ImageBlocks = AllocateZeroPool (ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize);
1182 if (ImageBlocks == NULL) {
1183 EfiReleaseLock (&mHiiDatabaseLock);
1184 return EFI_OUT_OF_RESOURCES;
1185 }
1186
1187 Part1Size = (UINT32) ((UINTN) CurrentImageBlock - (UINTN) ImagePackage->ImageBlock);
1188 Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;
1189 CopyMem (ImageBlocks, ImagePackage->ImageBlock, Part1Size);
1190
1191 //
1192 // Set the new image block
1193 //
1194 NewImageBlock = (EFI_HII_IMAGE_BLOCK *) ((UINT8 *) ImageBlocks + Part1Size);
1195 if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
1196 NewImageBlock->BlockType= EFI_HII_IIBT_IMAGE_24BIT_TRANS;
1197 } else {
1198 NewImageBlock->BlockType = EFI_HII_IIBT_IMAGE_24BIT;
1199 }
1200 WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Width, Image->Width);
1201 WriteUnaligned16 ((VOID *) &((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Height, Image->Height);
1202 CopyGopToRgbPixel (((EFI_HII_IIBT_IMAGE_24BIT_BLOCK *) NewImageBlock)->Bitmap.Bitmap,
1203 Image->Bitmap, (UINT32) Image->Width * Image->Height);
1204
1205 CopyMem ((UINT8 *) NewImageBlock + NewBlockSize, (UINT8 *) CurrentImageBlock + OldBlockSize, Part2Size);
1206
1207 FreePool (ImagePackage->ImageBlock);
1208 ImagePackage->ImageBlock = ImageBlocks;
1209 ImagePackage->ImageBlockSize += NewBlockSize - OldBlockSize;
1210 ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;
1211 PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;
1212
1213 //
1214 // Check whether need to get the contents of HiiDataBase.
1215 // Only after ReadyToBoot to do the export.
1216 //
1217 if (gExportAfterReadyToBoot) {
1218 HiiGetDatabaseInfo(&Private->HiiDatabase);
1219 }
1220
1221 EfiReleaseLock (&mHiiDatabaseLock);
1222 return EFI_SUCCESS;
1223
1224 }
1225
1226
1227 /**
1228 This function renders an image to a bitmap or the screen using the specified
1229 color and options. It draws the image on an existing bitmap, allocates a new
1230 bitmap or uses the screen. The images can be clipped.
1231
1232 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1233 @param Flags Describes how the image is to be drawn.
1234 @param Image Points to the image to be displayed.
1235 @param Blt If this points to a non-NULL on entry, this points
1236 to the image, which is Width pixels wide and
1237 Height pixels high. The image will be drawn onto
1238 this image and EFI_HII_DRAW_FLAG_CLIP is implied.
1239 If this points to a NULL on entry, then a buffer
1240 will be allocated to hold the generated image and
1241 the pointer updated on exit. It is the caller's
1242 responsibility to free this buffer.
1243 @param BltX Specifies the offset from the left and top edge of
1244 the output image of the first pixel in the image.
1245 @param BltY Specifies the offset from the left and top edge of
1246 the output image of the first pixel in the image.
1247
1248 @retval EFI_SUCCESS The image was successfully drawn.
1249 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
1250 @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
1251 @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
1252
1253 **/
1254 EFI_STATUS
1255 EFIAPI
1256 HiiDrawImage (
1257 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
1258 IN EFI_HII_DRAW_FLAGS Flags,
1259 IN CONST EFI_IMAGE_INPUT *Image,
1260 IN OUT EFI_IMAGE_OUTPUT **Blt,
1261 IN UINTN BltX,
1262 IN UINTN BltY
1263 )
1264 {
1265 EFI_STATUS Status;
1266 HII_DATABASE_PRIVATE_DATA *Private;
1267 BOOLEAN Transparent;
1268 EFI_IMAGE_OUTPUT *ImageOut;
1269 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
1270 UINTN BufferLen;
1271 UINT16 Width;
1272 UINT16 Height;
1273 UINTN Xpos;
1274 UINTN Ypos;
1275 UINTN OffsetY1;
1276 UINTN OffsetY2;
1277 EFI_FONT_DISPLAY_INFO *FontInfo;
1278 UINTN Index;
1279
1280 if (This == NULL || Image == NULL || Blt == NULL) {
1281 return EFI_INVALID_PARAMETER;
1282 }
1283
1284 if ((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP && *Blt == NULL) {
1285 return EFI_INVALID_PARAMETER;
1286 }
1287
1288 if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {
1289 return EFI_INVALID_PARAMETER;
1290 }
1291
1292 FontInfo = NULL;
1293
1294 //
1295 // Check whether the image will be drawn transparently or opaquely.
1296 //
1297 Transparent = FALSE;
1298 if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {
1299 Transparent = TRUE;
1300 } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE){
1301 Transparent = FALSE;
1302 } else {
1303 //
1304 // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
1305 // on the image's transparency setting.
1306 //
1307 if ((Image->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
1308 Transparent = TRUE;
1309 }
1310 }
1311
1312 //
1313 // Image cannot be drawn transparently if Blt points to NULL on entry.
1314 // Currently output to Screen transparently is not supported, either.
1315 //
1316 if (Transparent) {
1317 if (*Blt == NULL) {
1318 return EFI_INVALID_PARAMETER;
1319 } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
1320 return EFI_INVALID_PARAMETER;
1321 }
1322 }
1323
1324 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1325
1326 //
1327 // When Blt points to a non-NULL on entry, this image will be drawn onto
1328 // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
1329 // Otherwise a new bitmap will be allocated to hold this image.
1330 //
1331 if (*Blt != NULL) {
1332 //
1333 // Make sure the BltX and BltY is inside the Blt area.
1334 //
1335 if ((BltX >= (*Blt)->Width) || (BltY >= (*Blt)->Height)) {
1336 return EFI_INVALID_PARAMETER;
1337 }
1338
1339 //
1340 // Clip the image by (Width, Height)
1341 //
1342
1343 Width = Image->Width;
1344 Height = Image->Height;
1345
1346 if (Width > (*Blt)->Width - (UINT16)BltX) {
1347 Width = (*Blt)->Width - (UINT16)BltX;
1348 }
1349 if (Height > (*Blt)->Height - (UINT16)BltY) {
1350 Height = (*Blt)->Height - (UINT16)BltY;
1351 }
1352
1353 //
1354 // Prepare the buffer for the temporary image.
1355 // Make sure the buffer size doesn't overflow UINTN.
1356 //
1357 BufferLen = Width * Height;
1358 if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
1359 return EFI_OUT_OF_RESOURCES;
1360 }
1361 BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
1362 BltBuffer = AllocateZeroPool (BufferLen);
1363 if (BltBuffer == NULL) {
1364 return EFI_OUT_OF_RESOURCES;
1365 }
1366
1367 if (Width == Image->Width && Height == Image->Height) {
1368 CopyMem (BltBuffer, Image->Bitmap, BufferLen);
1369 } else {
1370 for (Ypos = 0; Ypos < Height; Ypos++) {
1371 OffsetY1 = Image->Width * Ypos;
1372 OffsetY2 = Width * Ypos;
1373 for (Xpos = 0; Xpos < Width; Xpos++) {
1374 BltBuffer[OffsetY2 + Xpos] = Image->Bitmap[OffsetY1 + Xpos];
1375 }
1376 }
1377 }
1378
1379 //
1380 // Draw the image to existing bitmap or screen depending on flag.
1381 //
1382 if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
1383 //
1384 // Caller should make sure the current UGA console is grarphic mode.
1385 //
1386
1387 //
1388 // Write the image directly to the output device specified by Screen.
1389 //
1390 Status = (*Blt)->Image.Screen->Blt (
1391 (*Blt)->Image.Screen,
1392 BltBuffer,
1393 EfiBltBufferToVideo,
1394 0,
1395 0,
1396 BltX,
1397 BltY,
1398 Width,
1399 Height,
1400 0
1401 );
1402 } else {
1403 //
1404 // Draw the image onto the existing bitmap specified by Bitmap.
1405 //
1406 Status = ImageToBlt (
1407 BltBuffer,
1408 BltX,
1409 BltY,
1410 Width,
1411 Height,
1412 Transparent,
1413 Blt
1414 );
1415
1416 }
1417
1418 FreePool (BltBuffer);
1419 return Status;
1420
1421 } else {
1422 //
1423 // Allocate a new bitmap to hold the incoming image.
1424 //
1425
1426 //
1427 // Make sure the final width and height doesn't overflow UINT16.
1428 //
1429 if ((BltX > (UINTN)MAX_UINT16 - Image->Width) || (BltY > (UINTN)MAX_UINT16 - Image->Height)) {
1430 return EFI_INVALID_PARAMETER;
1431 }
1432
1433 Width = Image->Width + (UINT16)BltX;
1434 Height = Image->Height + (UINT16)BltY;
1435
1436 //
1437 // Make sure the output image size doesn't overflow UINTN.
1438 //
1439 BufferLen = Width * Height;
1440 if (BufferLen > MAX_UINTN / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
1441 return EFI_OUT_OF_RESOURCES;
1442 }
1443 BufferLen *= sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
1444 BltBuffer = AllocateZeroPool (BufferLen);
1445 if (BltBuffer == NULL) {
1446 return EFI_OUT_OF_RESOURCES;
1447 }
1448
1449 ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1450 if (ImageOut == NULL) {
1451 FreePool (BltBuffer);
1452 return EFI_OUT_OF_RESOURCES;
1453 }
1454 ImageOut->Width = Width;
1455 ImageOut->Height = Height;
1456 ImageOut->Image.Bitmap = BltBuffer;
1457
1458 //
1459 // BUGBUG: Now all the "blank" pixels are filled with system default background
1460 // color. Not sure if it need to be updated or not.
1461 //
1462 Status = GetSystemFont (Private, &FontInfo, NULL);
1463 if (EFI_ERROR (Status)) {
1464 FreePool (BltBuffer);
1465 FreePool (ImageOut);
1466 return Status;
1467 }
1468 ASSERT (FontInfo != NULL);
1469 for (Index = 0; Index < (UINTN)Width * Height; Index++) {
1470 BltBuffer[Index] = FontInfo->BackgroundColor;
1471 }
1472 FreePool (FontInfo);
1473
1474 //
1475 // Draw the incoming image to the new created image.
1476 //
1477 *Blt = ImageOut;
1478 return ImageToBlt (
1479 Image->Bitmap,
1480 BltX,
1481 BltY,
1482 Image->Width,
1483 Image->Height,
1484 Transparent,
1485 Blt
1486 );
1487
1488 }
1489 }
1490
1491
1492 /**
1493 This function renders an image to a bitmap or the screen using the specified
1494 color and options. It draws the image on an existing bitmap, allocates a new
1495 bitmap or uses the screen. The images can be clipped.
1496
1497 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1498 @param Flags Describes how the image is to be drawn.
1499 @param PackageList The package list in the HII database to search for
1500 the specified image.
1501 @param ImageId The image's id, which is unique within
1502 PackageList.
1503 @param Blt If this points to a non-NULL on entry, this points
1504 to the image, which is Width pixels wide and
1505 Height pixels high. The image will be drawn onto
1506 this image and
1507 EFI_HII_DRAW_FLAG_CLIP is implied. If this points
1508 to a NULL on entry, then a buffer will be
1509 allocated to hold the generated image and the
1510 pointer updated on exit. It is the caller's
1511 responsibility to free this buffer.
1512 @param BltX Specifies the offset from the left and top edge of
1513 the output image of the first pixel in the image.
1514 @param BltY Specifies the offset from the left and top edge of
1515 the output image of the first pixel in the image.
1516
1517 @retval EFI_SUCCESS The image was successfully drawn.
1518 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
1519 @retval EFI_INVALID_PARAMETER The Blt was NULL.
1520 @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
1521 The specified PackageList is not in the database.
1522
1523 **/
1524 EFI_STATUS
1525 EFIAPI
1526 HiiDrawImageId (
1527 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
1528 IN EFI_HII_DRAW_FLAGS Flags,
1529 IN EFI_HII_HANDLE PackageList,
1530 IN EFI_IMAGE_ID ImageId,
1531 IN OUT EFI_IMAGE_OUTPUT **Blt,
1532 IN UINTN BltX,
1533 IN UINTN BltY
1534 )
1535 {
1536 EFI_STATUS Status;
1537 EFI_IMAGE_INPUT Image;
1538
1539 //
1540 // Check input parameter.
1541 //
1542 if (This == NULL || Blt == NULL) {
1543 return EFI_INVALID_PARAMETER;
1544 }
1545
1546 //
1547 // Get the specified Image.
1548 //
1549 Status = HiiGetImage (This, PackageList, ImageId, &Image);
1550 if (EFI_ERROR (Status)) {
1551 return Status;
1552 }
1553
1554 //
1555 // Draw this image.
1556 //
1557 Status = HiiDrawImage (This, Flags, &Image, Blt, BltX, BltY);
1558 if (Image.Bitmap != NULL) {
1559 FreePool (Image.Bitmap);
1560 }
1561 return Status;
1562 }
1563