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