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