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