]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
MdeModulePkg/HiiDatabase: Refine GetImageIdOrAddress
[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 /**
574 This function adds the image Image to the group of images owned by PackageList, and returns
575 a new image identifier (ImageId).
576
577 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
578 @param PackageList Handle of the package list where this image will
579 be added.
580 @param ImageId On return, contains the new image id, which is
581 unique within PackageList.
582 @param Image Points to the image.
583
584 @retval EFI_SUCCESS The new image was added successfully.
585 @retval EFI_NOT_FOUND The specified PackageList could not be found in
586 database.
587 @retval EFI_OUT_OF_RESOURCES Could not add the image due to lack of resources.
588 @retval EFI_INVALID_PARAMETER Image is NULL or ImageId is NULL.
589
590 **/
591 EFI_STATUS
592 EFIAPI
593 HiiNewImage (
594 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
595 IN EFI_HII_HANDLE PackageList,
596 OUT EFI_IMAGE_ID *ImageId,
597 IN CONST EFI_IMAGE_INPUT *Image
598 )
599 {
600 HII_DATABASE_PRIVATE_DATA *Private;
601 LIST_ENTRY *Link;
602 HII_DATABASE_RECORD *DatabaseRecord;
603 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
604 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
605 UINT8 *ImageBlock;
606 UINTN BlockSize;
607 UINT8 *NewBlock;
608 UINT8 *NewBlockPtr;
609 UINTN NewBlockSize;
610 EFI_IMAGE_INPUT *ImageIn;
611
612 if (This == NULL || ImageId == NULL || Image == NULL || Image->Bitmap == NULL) {
613 return EFI_INVALID_PARAMETER;
614 }
615
616 if (!IsHiiHandleValid (PackageList)) {
617 return EFI_NOT_FOUND;
618 }
619
620 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
621
622 //
623 // Get the specified package list
624 //
625
626 PackageListNode = NULL;
627
628 for (Link = Private->DatabaseList.ForwardLink;
629 Link != &Private->DatabaseList;
630 Link = Link->ForwardLink
631 ) {
632 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
633 if (DatabaseRecord->Handle == PackageList) {
634 PackageListNode = DatabaseRecord->PackageList;
635 break;
636 }
637 }
638
639 if (PackageListNode == NULL) {
640 return EFI_NOT_FOUND;
641 }
642
643 ImageIn = (EFI_IMAGE_INPUT *) Image;
644
645 NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
646 BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);
647
648 //
649 // Get the image package in the package list,
650 // or create a new image package if image package does not exist.
651 //
652 if (PackageListNode->ImagePkg != NULL) {
653 ImagePackage = PackageListNode->ImagePkg;
654
655 //
656 // Output the image id of the incoming image being inserted, which is the
657 // image id of the EFI_HII_IIBT_END block of old image package.
658 //
659 *ImageId = 0;
660 GetImageIdOrAddress (ImagePackage->ImageBlock, ImageId);
661
662 //
663 // Update the package's image block by appending the new block to the end.
664 //
665 BlockSize = ImagePackage->ImageBlockSize + NewBlockSize;
666 ImageBlock = (UINT8 *) AllocateZeroPool (BlockSize);
667 if (ImageBlock == NULL) {
668 return EFI_OUT_OF_RESOURCES;
669 }
670 //
671 // Copy the original content.
672 //
673 CopyMem (
674 ImageBlock,
675 ImagePackage->ImageBlock,
676 ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK)
677 );
678 FreePool (ImagePackage->ImageBlock);
679 ImagePackage->ImageBlock = (EFI_HII_IMAGE_BLOCK *) ImageBlock;
680 ImageBlock += ImagePackage->ImageBlockSize - sizeof (EFI_HII_IIBT_END_BLOCK);
681 //
682 // Temp memory to store new block.
683 //
684 NewBlock = AllocateZeroPool (NewBlockSize);
685 if (NewBlock == NULL) {
686 FreePool (ImagePackage->ImageBlock);
687 return EFI_OUT_OF_RESOURCES;
688 }
689 NewBlockPtr = NewBlock;
690
691 //
692 // Update the length record.
693 //
694 ImagePackage->ImageBlockSize = (UINT32) BlockSize;
695 ImagePackage->ImagePkgHdr.Header.Length += (UINT32) NewBlockSize;
696 PackageListNode->PackageListHdr.PackageLength += (UINT32) NewBlockSize;
697
698 } else {
699 //
700 // The specified package list does not contain image package.
701 // Create one to add this image block.
702 //
703 ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
704 if (ImagePackage == NULL) {
705 return EFI_OUT_OF_RESOURCES;
706 }
707 //
708 // Output the image id of the incoming image being inserted, which is the
709 // first image block so that id is initially to one.
710 //
711 *ImageId = 1;
712 BlockSize = sizeof (EFI_HII_IIBT_END_BLOCK) + NewBlockSize;
713 //
714 // Fill in image package header.
715 //
716 ImagePackage->ImagePkgHdr.Header.Length = (UINT32) BlockSize + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
717 ImagePackage->ImagePkgHdr.Header.Type = EFI_HII_PACKAGE_IMAGES;
718 ImagePackage->ImagePkgHdr.ImageInfoOffset = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
719 ImagePackage->ImagePkgHdr.PaletteInfoOffset = 0;
720
721 //
722 // Fill in palette info.
723 //
724 ImagePackage->PaletteBlock = NULL;
725 ImagePackage->PaletteInfoSize = 0;
726
727 //
728 // Fill in image blocks.
729 //
730 ImagePackage->ImageBlockSize = (UINT32) BlockSize;
731 ImagePackage->ImageBlock = AllocateZeroPool (BlockSize);
732 if (ImagePackage->ImageBlock == NULL) {
733 FreePool (ImagePackage);
734 return EFI_OUT_OF_RESOURCES;
735 }
736 ImageBlock = (UINT8 *) ImagePackage->ImageBlock;
737
738 //
739 // Temp memory to store new block.
740 //
741 NewBlock = AllocateZeroPool (NewBlockSize);
742 if (NewBlock == NULL) {
743 FreePool (ImagePackage->ImageBlock);
744 FreePool (ImagePackage);
745 return EFI_OUT_OF_RESOURCES;
746 }
747 NewBlockPtr = NewBlock;
748
749 //
750 // Insert this image package.
751 //
752 PackageListNode->ImagePkg = ImagePackage;
753 PackageListNode->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
754 }
755
756 //
757 // Append the new block here
758 //
759 if (ImageIn->Flags == EFI_IMAGE_TRANSPARENT) {
760 *NewBlock = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
761 } else {
762 *NewBlock = EFI_HII_IIBT_IMAGE_24BIT;
763 }
764 NewBlock++;
765 CopyMem (NewBlock, &ImageIn->Width, sizeof (UINT16));
766 NewBlock += sizeof (UINT16);
767 CopyMem (NewBlock, &ImageIn->Height, sizeof (UINT16));
768 NewBlock += sizeof (UINT16);
769 CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlock, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);
770
771 CopyMem (ImageBlock, NewBlockPtr, NewBlockSize);
772 FreePool (NewBlockPtr);
773
774 //
775 // Append the block end
776 //
777 ImageBlock += NewBlockSize;
778 ((EFI_HII_IIBT_END_BLOCK *) (ImageBlock))->Header.BlockType = EFI_HII_IIBT_END;
779
780 //
781 // Check whether need to get the contents of HiiDataBase.
782 // Only after ReadyToBoot to do the export.
783 //
784 if (gExportAfterReadyToBoot) {
785 HiiGetDatabaseInfo(&Private->HiiDatabase);
786 }
787
788 return EFI_SUCCESS;
789 }
790
791
792 /**
793 This function retrieves the image specified by ImageId which is associated with
794 the specified PackageList and copies it into the buffer specified by Image.
795
796 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
797 @param PackageList Handle of the package list where this image will
798 be searched.
799 @param ImageId The image's id,, which is unique within
800 PackageList.
801 @param Image Points to the image.
802
803 @retval EFI_SUCCESS The new image was returned successfully.
804 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
805 database. The specified PackageList is not in the database.
806 @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to
807 hold the image.
808 @retval EFI_INVALID_PARAMETER The Image or ImageSize was NULL.
809 @retval EFI_OUT_OF_RESOURCES The bitmap could not be retrieved because there was not
810 enough memory.
811
812 **/
813 EFI_STATUS
814 EFIAPI
815 HiiGetImage (
816 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
817 IN EFI_HII_HANDLE PackageList,
818 IN EFI_IMAGE_ID ImageId,
819 OUT EFI_IMAGE_INPUT *Image
820 )
821 {
822 HII_DATABASE_PRIVATE_DATA *Private;
823 LIST_ENTRY *Link;
824 HII_DATABASE_RECORD *DatabaseRecord;
825 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
826 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
827 UINT8 *ImageBlock;
828 EFI_IMAGE_ID LocalImageId;
829 UINT8 BlockType;
830 EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
831 UINT16 Width;
832 UINT16 Height;
833 UINTN ImageLength;
834 BOOLEAN Flag;
835 UINT8 *PaletteInfo;
836 UINT8 PaletteIndex;
837 UINT16 PaletteSize;
838
839 if (This == NULL || Image == NULL || ImageId < 1) {
840 return EFI_INVALID_PARAMETER;
841 }
842
843 if (!IsHiiHandleValid (PackageList)) {
844 return EFI_NOT_FOUND;
845 }
846
847 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
848
849 //
850 // Get the specified package list and image package.
851 //
852 PackageListNode = NULL;
853 for (Link = Private->DatabaseList.ForwardLink;
854 Link != &Private->DatabaseList;
855 Link = Link->ForwardLink
856 ) {
857 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
858 if (DatabaseRecord->Handle == PackageList) {
859 PackageListNode = DatabaseRecord->PackageList;
860 break;
861 }
862 }
863 if (PackageListNode == NULL) {
864 return EFI_NOT_FOUND;
865 }
866 ImagePackage = PackageListNode->ImagePkg;
867 if (ImagePackage == NULL) {
868 return EFI_NOT_FOUND;
869 }
870
871 //
872 // Find the image block specified by ImageId
873 //
874 LocalImageId = ImageId;
875 ImageBlock = (UINT8 *) GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);
876 if (ImageBlock == NULL) {
877 return EFI_NOT_FOUND;
878 }
879
880 Flag = FALSE;
881 BlockType = *ImageBlock;
882
883 switch (BlockType) {
884 case EFI_HII_IIBT_IMAGE_JPEG:
885 //
886 // BUGBUG: need to be supported as soon as image tool is designed.
887 //
888 return EFI_UNSUPPORTED;
889
890 case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
891 case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
892 case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
893 Flag = TRUE;
894 //
895 // fall through
896 //
897 case EFI_HII_IIBT_IMAGE_1BIT:
898 case EFI_HII_IIBT_IMAGE_4BIT:
899 case EFI_HII_IIBT_IMAGE_8BIT:
900 //
901 // Use the common block code since the definition of these structures is the same.
902 //
903 CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
904 ImageLength = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) *
905 (Iibt1bit.Bitmap.Width * Iibt1bit.Bitmap.Height);
906 Image->Bitmap = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (ImageLength);
907 if (Image->Bitmap == NULL) {
908 return EFI_OUT_OF_RESOURCES;
909 }
910
911 if (Flag) {
912 Image->Flags = EFI_IMAGE_TRANSPARENT;
913 }
914 Image->Width = Iibt1bit.Bitmap.Width;
915 Image->Height = Iibt1bit.Bitmap.Height;
916
917 PaletteInfo = ImagePackage->PaletteBlock + sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
918 for (PaletteIndex = 1; PaletteIndex < Iibt1bit.PaletteIndex; PaletteIndex++) {
919 CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
920 PaletteInfo += PaletteSize + sizeof (UINT16);
921 }
922 ASSERT (PaletteIndex == Iibt1bit.PaletteIndex);
923
924 //
925 // Output bitmap data
926 //
927 if (BlockType == EFI_HII_IIBT_IMAGE_1BIT || BlockType == EFI_HII_IIBT_IMAGE_1BIT_TRANS) {
928 Output1bitPixel (
929 Image,
930 (UINT8 *) ((UINTN)ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8)),
931 (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
932 );
933 } else if (BlockType == EFI_HII_IIBT_IMAGE_4BIT || BlockType == EFI_HII_IIBT_IMAGE_4BIT_TRANS) {
934 Output4bitPixel (
935 Image,
936 (UINT8 *) ((UINTN)ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8)),
937 (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
938 );
939 } else {
940 Output8bitPixel (
941 Image,
942 (UINT8 *) ((UINTN)ImageBlock + sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8)),
943 (EFI_HII_IMAGE_PALETTE_INFO *) PaletteInfo
944 );
945 }
946
947 return EFI_SUCCESS;
948
949 case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
950 Flag = TRUE;
951 //
952 // fall through
953 //
954 case EFI_HII_IIBT_IMAGE_24BIT:
955 CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
956 CopyMem (
957 &Height,
958 ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
959 sizeof (UINT16)
960 );
961 ImageLength = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (Width * Height);
962 Image->Bitmap = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (ImageLength);
963 if (Image->Bitmap == NULL) {
964 return EFI_OUT_OF_RESOURCES;
965 }
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
982 default:
983 return EFI_NOT_FOUND;
984 }
985 }
986
987
988 /**
989 This function updates the image specified by ImageId in the specified PackageListHandle to
990 the image specified by Image.
991
992 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
993 @param PackageList The package list containing the images.
994 @param ImageId The image's id,, which is unique within
995 PackageList.
996 @param Image Points to the image.
997
998 @retval EFI_SUCCESS The new image was updated successfully.
999 @retval EFI_NOT_FOUND The image specified by ImageId is not in the
1000 database. The specified PackageList is not in the database.
1001 @retval EFI_INVALID_PARAMETER The Image was NULL.
1002
1003 **/
1004 EFI_STATUS
1005 EFIAPI
1006 HiiSetImage (
1007 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
1008 IN EFI_HII_HANDLE PackageList,
1009 IN EFI_IMAGE_ID ImageId,
1010 IN CONST EFI_IMAGE_INPUT *Image
1011 )
1012 {
1013 HII_DATABASE_PRIVATE_DATA *Private;
1014 LIST_ENTRY *Link;
1015 HII_DATABASE_RECORD *DatabaseRecord;
1016 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1017 HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
1018 UINT8 *ImageBlock;
1019 EFI_IMAGE_ID LocalImageId;
1020 UINT8 BlockType;
1021 EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit;
1022 EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit;
1023 EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit;
1024 UINT16 Width;
1025 UINT16 Height;
1026 UINT32 BlockSize;
1027 UINT32 NewBlockSize;
1028 UINT32 OldBlockSize;
1029 EFI_IMAGE_INPUT *ImageIn;
1030 UINT8 *NewBlock;
1031 UINT8 *NewBlockPtr;
1032 UINT8 *Block;
1033 UINT8 *BlockPtr;
1034 UINT32 Part1Size;
1035 UINT32 Part2Size;
1036
1037 if (This == NULL || Image == NULL || ImageId < 1 || Image->Bitmap == NULL) {
1038 return EFI_INVALID_PARAMETER;
1039 }
1040
1041 if (!IsHiiHandleValid (PackageList)) {
1042 return EFI_NOT_FOUND;
1043 }
1044
1045 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1046
1047 //
1048 // Get the specified package list and image package.
1049 //
1050 PackageListNode = NULL;
1051 for (Link = Private->DatabaseList.ForwardLink;
1052 Link != &Private->DatabaseList;
1053 Link = Link->ForwardLink
1054 ) {
1055 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1056 if (DatabaseRecord->Handle == PackageList) {
1057 PackageListNode = DatabaseRecord->PackageList;
1058 break;
1059 }
1060 }
1061 if (PackageListNode == NULL) {
1062 return EFI_NOT_FOUND;
1063 }
1064 ImagePackage = PackageListNode->ImagePkg;
1065 if (ImagePackage == NULL) {
1066 return EFI_NOT_FOUND;
1067 }
1068
1069 //
1070 // Find the image block specified by ImageId
1071 //
1072 LocalImageId = ImageId;
1073 ImageBlock = (UINT8 *) GetImageIdOrAddress (ImagePackage->ImageBlock, &LocalImageId);
1074 if (ImageBlock == NULL) {
1075 return EFI_NOT_FOUND;
1076 }
1077
1078 BlockType = *ImageBlock;
1079
1080 //
1081 // Get the size of original image block. Use some common block code here
1082 // since the definition of some structures is the same.
1083 //
1084 switch (BlockType) {
1085 case EFI_HII_IIBT_IMAGE_JPEG:
1086 //
1087 // BUGBUG: need to be supported as soon as image tool is designed.
1088 //
1089 return EFI_UNSUPPORTED;
1090
1091 case EFI_HII_IIBT_IMAGE_1BIT:
1092 case EFI_HII_IIBT_IMAGE_1BIT_TRANS:
1093 CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK));
1094 OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) +
1095 BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height);
1096 break;
1097 case EFI_HII_IIBT_IMAGE_4BIT:
1098 case EFI_HII_IIBT_IMAGE_4BIT_TRANS:
1099 CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK));
1100 OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) +
1101 BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height);
1102 break;
1103 case EFI_HII_IIBT_IMAGE_8BIT:
1104 case EFI_HII_IIBT_IMAGE_8BIT_TRANS:
1105 CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK));
1106 OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) +
1107 BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height);
1108 break;
1109 case EFI_HII_IIBT_IMAGE_24BIT:
1110 case EFI_HII_IIBT_IMAGE_24BIT_TRANS:
1111 CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16));
1112 CopyMem (
1113 &Height,
1114 ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16),
1115 sizeof (UINT16)
1116 );
1117 OldBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
1118 BITMAP_LEN_24_BIT (Width , Height);
1119 break;
1120 default:
1121 return EFI_NOT_FOUND;
1122 }
1123
1124 //
1125 // Create the new image block according to input image.
1126 //
1127 ImageIn = (EFI_IMAGE_INPUT *) Image;
1128 NewBlockSize = sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) +
1129 BITMAP_LEN_24_BIT (ImageIn->Width, ImageIn->Height);
1130 NewBlock = (UINT8 *) AllocateZeroPool (NewBlockSize);
1131 if (NewBlock == NULL) {
1132 return EFI_OUT_OF_RESOURCES;
1133 }
1134
1135 NewBlockPtr = NewBlock;
1136 if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
1137 *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT_TRANS;
1138 } else {
1139 *NewBlockPtr = EFI_HII_IIBT_IMAGE_24BIT;
1140 }
1141 NewBlockPtr++;
1142
1143 CopyMem (NewBlockPtr, &ImageIn->Width, sizeof (UINT16));
1144 NewBlockPtr += sizeof (UINT16);
1145 CopyMem (NewBlockPtr, &ImageIn->Height, sizeof (UINT16));
1146 NewBlockPtr += sizeof (UINT16);
1147
1148 CopyGopToRgbPixel ((EFI_HII_RGB_PIXEL *) NewBlockPtr, ImageIn->Bitmap, ImageIn->Width * ImageIn->Height);
1149
1150 //
1151 // Adjust the image package to remove the original block firstly then add the new block.
1152 //
1153 BlockSize = ImagePackage->ImageBlockSize + NewBlockSize - OldBlockSize;
1154 Block = (UINT8 *) AllocateZeroPool (BlockSize);
1155 if (Block == NULL) {
1156 FreePool (NewBlock);
1157 return EFI_OUT_OF_RESOURCES;
1158 }
1159
1160 BlockPtr = Block;
1161 Part1Size = (UINT32) (ImageBlock - (UINT8 *) ImagePackage->ImageBlock);
1162 Part2Size = ImagePackage->ImageBlockSize - Part1Size - OldBlockSize;
1163 CopyMem (BlockPtr, ImagePackage->ImageBlock, Part1Size);
1164 BlockPtr += Part1Size;
1165 CopyMem (BlockPtr, NewBlock, NewBlockSize);
1166 BlockPtr += NewBlockSize;
1167 CopyMem (BlockPtr, ImageBlock + OldBlockSize, Part2Size);
1168
1169 FreePool (ImagePackage->ImageBlock);
1170 FreePool (NewBlock);
1171 ImagePackage->ImageBlock = (EFI_HII_IMAGE_BLOCK *) Block;
1172 ImagePackage->ImageBlockSize = BlockSize;
1173 ImagePackage->ImagePkgHdr.Header.Length += NewBlockSize - OldBlockSize;
1174 PackageListNode->PackageListHdr.PackageLength += NewBlockSize - OldBlockSize;
1175
1176 //
1177 // Check whether need to get the contents of HiiDataBase.
1178 // Only after ReadyToBoot to do the export.
1179 //
1180 if (gExportAfterReadyToBoot) {
1181 HiiGetDatabaseInfo(&Private->HiiDatabase);
1182 }
1183
1184 return EFI_SUCCESS;
1185
1186 }
1187
1188
1189 /**
1190 This function renders an image to a bitmap or the screen using the specified
1191 color and options. It draws the image on an existing bitmap, allocates a new
1192 bitmap or uses the screen. The images can be clipped.
1193
1194 @param This A pointer to the EFI_HII_IMAGE_PROTOCOL instance.
1195 @param Flags Describes how the image is to be drawn.
1196 @param Image Points to the image to be displayed.
1197 @param Blt If this points to a non-NULL on entry, this points
1198 to the image, which is Width pixels wide and
1199 Height pixels high. The image will be drawn onto
1200 this image and EFI_HII_DRAW_FLAG_CLIP is implied.
1201 If this points to a NULL on entry, then a buffer
1202 will be allocated to hold the generated image and
1203 the pointer updated on exit. It is the caller's
1204 responsibility to free this buffer.
1205 @param BltX Specifies the offset from the left and top edge of
1206 the output image of the first pixel in the image.
1207 @param BltY Specifies the offset from the left and top edge of
1208 the output image of the first pixel in the image.
1209
1210 @retval EFI_SUCCESS The image was successfully drawn.
1211 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
1212 @retval EFI_INVALID_PARAMETER The Image or Blt was NULL.
1213 @retval EFI_INVALID_PARAMETER Any combination of Flags is invalid.
1214
1215 **/
1216 EFI_STATUS
1217 EFIAPI
1218 HiiDrawImage (
1219 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
1220 IN EFI_HII_DRAW_FLAGS Flags,
1221 IN CONST EFI_IMAGE_INPUT *Image,
1222 IN OUT EFI_IMAGE_OUTPUT **Blt,
1223 IN UINTN BltX,
1224 IN UINTN BltY
1225 )
1226 {
1227 EFI_STATUS Status;
1228 HII_DATABASE_PRIVATE_DATA *Private;
1229 BOOLEAN Transparent;
1230 EFI_IMAGE_INPUT *ImageIn;
1231 EFI_IMAGE_OUTPUT *ImageOut;
1232 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
1233 UINTN BufferLen;
1234 UINTN Width;
1235 UINTN Height;
1236 UINTN Xpos;
1237 UINTN Ypos;
1238 UINTN OffsetY1;
1239 UINTN OffsetY2;
1240 EFI_FONT_DISPLAY_INFO *FontInfo;
1241 UINTN Index;
1242
1243 if (This == NULL || Image == NULL || Blt == NULL) {
1244 return EFI_INVALID_PARAMETER;
1245 }
1246
1247 if ((Flags & EFI_HII_DRAW_FLAG_CLIP) == EFI_HII_DRAW_FLAG_CLIP && *Blt == NULL) {
1248 return EFI_INVALID_PARAMETER;
1249 }
1250
1251 if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_TRANSPARENT) {
1252 return EFI_INVALID_PARAMETER;
1253 }
1254
1255 FontInfo = NULL;
1256 ImageIn = (EFI_IMAGE_INPUT *) Image;
1257
1258 //
1259 // Check whether the image will be drawn transparently or opaquely.
1260 //
1261 Transparent = FALSE;
1262 if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_TRANS) {
1263 Transparent = TRUE;
1264 } else if ((Flags & EFI_HII_DRAW_FLAG_TRANSPARENT) == EFI_HII_DRAW_FLAG_FORCE_OPAQUE){
1265 Transparent = FALSE;
1266 } else {
1267 //
1268 // Now EFI_HII_DRAW_FLAG_DEFAULT is set, whether image will be drawn depending
1269 // on the image's transparency setting.
1270 //
1271 if ((ImageIn->Flags & EFI_IMAGE_TRANSPARENT) == EFI_IMAGE_TRANSPARENT) {
1272 Transparent = TRUE;
1273 }
1274 }
1275
1276 //
1277 // Image cannot be drawn transparently if Blt points to NULL on entry.
1278 // Currently output to Screen transparently is not supported, either.
1279 //
1280 if (Transparent) {
1281 if (*Blt == NULL) {
1282 return EFI_INVALID_PARAMETER;
1283 } else if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
1284 return EFI_INVALID_PARAMETER;
1285 }
1286 }
1287
1288 Private = HII_IMAGE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1289
1290 //
1291 // When Blt points to a non-NULL on entry, this image will be drawn onto
1292 // this bitmap or screen pointed by "*Blt" and EFI_HII_DRAW_FLAG_CLIP is implied.
1293 // Otherwise a new bitmap will be allocated to hold this image.
1294 //
1295 if (*Blt != NULL) {
1296 //
1297 // Clip the image by (Width, Height)
1298 //
1299
1300 Width = ImageIn->Width;
1301 Height = ImageIn->Height;
1302
1303 if (Width > (*Blt)->Width - BltX) {
1304 Width = (*Blt)->Width - BltX;
1305 }
1306 if (Height > (*Blt)->Height - BltY) {
1307 Height = (*Blt)->Height - BltY;
1308 }
1309
1310 BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
1311 BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
1312 if (BltBuffer == NULL) {
1313 return EFI_OUT_OF_RESOURCES;
1314 }
1315
1316 if (Width == ImageIn->Width && Height == ImageIn->Height) {
1317 CopyMem (BltBuffer, ImageIn->Bitmap, BufferLen);
1318 } else {
1319 for (Ypos = 0; Ypos < Height; Ypos++) {
1320 OffsetY1 = ImageIn->Width * Ypos;
1321 OffsetY2 = Width * Ypos;
1322 for (Xpos = 0; Xpos < Width; Xpos++) {
1323 BltBuffer[OffsetY2 + Xpos] = ImageIn->Bitmap[OffsetY1 + Xpos];
1324 }
1325 }
1326 }
1327
1328 //
1329 // Draw the image to existing bitmap or screen depending on flag.
1330 //
1331 if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
1332 //
1333 // Caller should make sure the current UGA console is grarphic mode.
1334 //
1335
1336 //
1337 // Write the image directly to the output device specified by Screen.
1338 //
1339 Status = (*Blt)->Image.Screen->Blt (
1340 (*Blt)->Image.Screen,
1341 BltBuffer,
1342 EfiBltBufferToVideo,
1343 0,
1344 0,
1345 BltX,
1346 BltY,
1347 Width,
1348 Height,
1349 0
1350 );
1351 } else {
1352 //
1353 // Draw the image onto the existing bitmap specified by Bitmap.
1354 //
1355 Status = ImageToBlt (
1356 BltBuffer,
1357 BltX,
1358 BltY,
1359 Width,
1360 Height,
1361 Transparent,
1362 Blt
1363 );
1364
1365 }
1366
1367 FreePool (BltBuffer);
1368 return Status;
1369
1370 } else {
1371 //
1372 // Allocate a new bitmap to hold the incoming image.
1373 //
1374 Width = ImageIn->Width + BltX;
1375 Height = ImageIn->Height + BltY;
1376
1377 BufferLen = Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
1378 BltBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (BufferLen);
1379 if (BltBuffer == NULL) {
1380 return EFI_OUT_OF_RESOURCES;
1381 }
1382
1383 ImageOut = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
1384 if (ImageOut == NULL) {
1385 FreePool (BltBuffer);
1386 return EFI_OUT_OF_RESOURCES;
1387 }
1388 ImageOut->Width = (UINT16) Width;
1389 ImageOut->Height = (UINT16) Height;
1390 ImageOut->Image.Bitmap = BltBuffer;
1391
1392 //
1393 // BUGBUG: Now all the "blank" pixels are filled with system default background
1394 // color. Not sure if it need to be updated or not.
1395 //
1396 Status = GetSystemFont (Private, &FontInfo, NULL);
1397 if (EFI_ERROR (Status)) {
1398 FreePool (BltBuffer);
1399 FreePool (ImageOut);
1400 return Status;
1401 }
1402 ASSERT (FontInfo != NULL);
1403 for (Index = 0; Index < Width * Height; Index++) {
1404 BltBuffer[Index] = FontInfo->BackgroundColor;
1405 }
1406 FreePool (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 BltX Specifies the offset from the left and top edge of
1447 the output image of the first pixel in the image.
1448 @param BltY Specifies the offset from the left and top edge of
1449 the output image of the first pixel in the image.
1450
1451 @retval EFI_SUCCESS The image was successfully drawn.
1452 @retval EFI_OUT_OF_RESOURCES Unable to allocate an output buffer for Blt.
1453 @retval EFI_INVALID_PARAMETER The Blt was NULL.
1454 @retval EFI_NOT_FOUND The image specified by ImageId is not in the database.
1455 The specified PackageList is not in the database.
1456
1457 **/
1458 EFI_STATUS
1459 EFIAPI
1460 HiiDrawImageId (
1461 IN CONST EFI_HII_IMAGE_PROTOCOL *This,
1462 IN EFI_HII_DRAW_FLAGS Flags,
1463 IN EFI_HII_HANDLE PackageList,
1464 IN EFI_IMAGE_ID ImageId,
1465 IN OUT EFI_IMAGE_OUTPUT **Blt,
1466 IN UINTN BltX,
1467 IN UINTN BltY
1468 )
1469 {
1470 EFI_STATUS Status;
1471 EFI_IMAGE_INPUT Image;
1472
1473 //
1474 // Check input parameter.
1475 //
1476 if (This == NULL || Blt == 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 Status = HiiGetImage (This, PackageList, ImageId, &Image);
1488 if (EFI_ERROR (Status)) {
1489 return Status;
1490 }
1491
1492 //
1493 // Draw this image.
1494 //
1495 Status = HiiDrawImage (This, Flags, &Image, Blt, BltX, BltY);
1496 if (Image.Bitmap != NULL) {
1497 FreePool (Image.Bitmap);
1498 }
1499 return Status;
1500 }
1501