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