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