MdeModulePkg/CapsuleLib: Fix runtime issue
[mirror_edk2.git] / MdeModulePkg / Library / DxeCapsuleLibFmp / DxeCapsuleLib.c
1 /** @file
2 DXE capsule library.
3
4 Caution: This module requires additional review when modified.
5 This module will have external input - capsule image.
6 This external input must be validated carefully to avoid security issue like
7 buffer overflow, integer overflow.
8
9 SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),
10 ValidateFmpCapsule(), DisplayCapsuleImage(), ConvertBmpToGopBlt() will
11 receive untrusted input and do basic validation.
12
13 Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
14 This program and the accompanying materials
15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution. The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
18
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21
22 **/
23
24 #include <PiDxe.h>
25
26 #include <IndustryStandard/Bmp.h>
27 #include <IndustryStandard/WindowsUxCapsule.h>
28
29 #include <Guid/FmpCapsule.h>
30 #include <Guid/SystemResourceTable.h>
31 #include <Guid/EventGroup.h>
32
33 #include <Library/BaseLib.h>
34 #include <Library/DebugLib.h>
35 #include <Library/BaseMemoryLib.h>
36 #include <Library/DxeServicesTableLib.h>
37 #include <Library/UefiBootServicesTableLib.h>
38 #include <Library/UefiRuntimeServicesTableLib.h>
39 #include <Library/MemoryAllocationLib.h>
40 #include <Library/CapsuleLib.h>
41 #include <Library/DevicePathLib.h>
42 #include <Library/UefiLib.h>
43 #include <Library/PcdLib.h>
44
45 #include <Protocol/GraphicsOutput.h>
46 #include <Protocol/EsrtManagement.h>
47 #include <Protocol/FirmwareManagement.h>
48 #include <Protocol/DevicePath.h>
49
50 BOOLEAN mDxeCapsuleLibEndOfDxe = FALSE;
51 EFI_EVENT mDxeCapsuleLibEndOfDxeEvent = NULL;
52
53 /**
54 Initialize capsule related variables.
55 **/
56 VOID
57 InitCapsuleVariable (
58 VOID
59 );
60
61 /**
62 Record capsule status variable.
63
64 @param[in] CapsuleHeader The capsule image header
65 @param[in] CapsuleStatus The capsule process stauts
66
67 @retval EFI_SUCCESS The capsule status variable is recorded.
68 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
69 **/
70 EFI_STATUS
71 RecordCapsuleStatusVariable (
72 IN EFI_CAPSULE_HEADER *CapsuleHeader,
73 IN EFI_STATUS CapsuleStatus
74 );
75
76 /**
77 Record FMP capsule status variable.
78
79 @param[in] CapsuleHeader The capsule image header
80 @param[in] CapsuleStatus The capsule process stauts
81 @param[in] PayloadIndex FMP payload index
82 @param[in] ImageHeader FMP image header
83 @param[in] FmpDevicePath DevicePath associated with the FMP producer
84
85 @retval EFI_SUCCESS The capsule status variable is recorded.
86 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
87 **/
88 EFI_STATUS
89 RecordFmpCapsuleStatusVariable (
90 IN EFI_CAPSULE_HEADER *CapsuleHeader,
91 IN EFI_STATUS CapsuleStatus,
92 IN UINTN PayloadIndex,
93 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
94 IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL
95 );
96
97 /**
98 Function indicate the current completion progress of the firmware
99 update. Platform may override with own specific progress function.
100
101 @param[in] Completion A value between 1 and 100 indicating the current completion progress of the firmware update
102
103 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
104 **/
105 EFI_STATUS
106 EFIAPI
107 Update_Image_Progress (
108 IN UINTN Completion
109 )
110 {
111 return EFI_SUCCESS;
112 }
113
114 /**
115 Return if this CapsuleGuid is a FMP capsule GUID or not.
116
117 @param[in] CapsuleGuid A pointer to EFI_GUID
118
119 @retval TRUE It is a FMP capsule GUID.
120 @retval FALSE It is not a FMP capsule GUID.
121 **/
122 BOOLEAN
123 IsFmpCapsuleGuid (
124 IN EFI_GUID *CapsuleGuid
125 )
126 {
127 if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) {
128 return TRUE;
129 }
130
131 return FALSE;
132 }
133
134 /**
135 Validate if it is valid capsule header
136
137 Caution: This function may receive untrusted input.
138
139 This function assumes the caller provided correct CapsuleHeader pointer
140 and CapsuleSize.
141
142 This function validates the fields in EFI_CAPSULE_HEADER.
143
144 @param[in] CapsuleHeader Points to a capsule header.
145 @param[in] CapsuleSize Size of the whole capsule image.
146
147 **/
148 BOOLEAN
149 IsValidCapsuleHeader (
150 IN EFI_CAPSULE_HEADER *CapsuleHeader,
151 IN UINT64 CapsuleSize
152 )
153 {
154 if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
155 return FALSE;
156 }
157 if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
158 return FALSE;
159 }
160 return TRUE;
161 }
162
163 /**
164 Validate Fmp capsules layout.
165
166 Caution: This function may receive untrusted input.
167
168 This function assumes the caller validated the capsule by using
169 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
170 The capsule buffer size is CapsuleHeader->CapsuleImageSize.
171
172 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
173 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
174
175 This function need support nested FMP capsule.
176
177 @param[in] CapsuleHeader Points to a capsule header.
178 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
179
180 @retval EFI_SUCESS Input capsule is a correct FMP capsule.
181 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
182 **/
183 EFI_STATUS
184 ValidateFmpCapsule (
185 IN EFI_CAPSULE_HEADER *CapsuleHeader,
186 OUT UINT16 *EmbeddedDriverCount OPTIONAL
187 )
188 {
189 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
190 UINT8 *EndOfCapsule;
191 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
192 UINT8 *EndOfPayload;
193 UINT64 *ItemOffsetList;
194 UINT32 ItemNum;
195 UINTN Index;
196 UINTN FmpCapsuleSize;
197 UINTN FmpCapsuleHeaderSize;
198 UINT64 FmpImageSize;
199 UINTN FmpImageHeaderSize;
200
201 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
202 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), EmbeddedDriverCount);
203 }
204
205 if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {
206 DEBUG((DEBUG_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
207 return EFI_INVALID_PARAMETER;
208 }
209
210 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
211 EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;
212 FmpCapsuleSize = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;
213
214 if (FmpCapsuleSize < sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {
215 DEBUG((DEBUG_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));
216 return EFI_INVALID_PARAMETER;
217 }
218
219 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
220 if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
221 DEBUG((DEBUG_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));
222 return EFI_INVALID_PARAMETER;
223 }
224 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
225
226 // No overflow
227 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
228
229 if ((FmpCapsuleSize - sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof(UINT64) < ItemNum) {
230 DEBUG((DEBUG_ERROR, "ItemNum(0x%x) too big\n", ItemNum));
231 return EFI_INVALID_PARAMETER;
232 }
233 FmpCapsuleHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64)*ItemNum;
234
235 // Check ItemOffsetList
236 for (Index = 0; Index < ItemNum; Index++) {
237 if (ItemOffsetList[Index] >= FmpCapsuleSize) {
238 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));
239 return EFI_INVALID_PARAMETER;
240 }
241 if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {
242 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));
243 return EFI_INVALID_PARAMETER;
244 }
245 //
246 // All the address in ItemOffsetList must be stored in ascending order
247 //
248 if (Index > 0) {
249 if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {
250 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index, ItemOffsetList[Index - 1]));
251 return EFI_INVALID_PARAMETER;
252 }
253 }
254 }
255
256 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER
257 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
258 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
259 if (Index == ItemNum - 1) {
260 EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);
261 } else {
262 EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];
263 }
264 FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];
265
266 if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {
267 DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));
268 return EFI_INVALID_PARAMETER;
269 }
270 FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);
271 if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||
272 (ImageHeader->Version < 1)) {
273 DEBUG((DEBUG_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));
274 return EFI_INVALID_PARAMETER;
275 }
276 if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
277 FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
278 }
279
280 // No overflow
281 if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {
282 DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize, ImageHeader->UpdateImageSize, ImageHeader->UpdateVendorCodeSize));
283 return EFI_INVALID_PARAMETER;
284 }
285 }
286
287 if (ItemNum == 0) {
288 //
289 // No driver & payload element in FMP
290 //
291 EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);
292 if (EndOfPayload != EndOfCapsule) {
293 DEBUG((DEBUG_ERROR, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload, EndOfCapsule));
294 return EFI_INVALID_PARAMETER;
295 }
296 return EFI_UNSUPPORTED;
297 }
298
299 if (EmbeddedDriverCount != NULL) {
300 *EmbeddedDriverCount = FmpCapsuleHeader->EmbeddedDriverCount;
301 }
302
303 return EFI_SUCCESS;
304 }
305
306 /**
307 Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer
308 is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt
309 buffer is passed in it will be used if it is big enough.
310
311 Caution: This function may receive untrusted input.
312
313 @param[in] BmpImage Pointer to BMP file
314 @param[in] BmpImageSize Number of bytes in BmpImage
315 @param[in, out] GopBlt Buffer containing GOP version of BmpImage.
316 @param[in, out] GopBltSize Size of GopBlt in bytes.
317 @param[out] PixelHeight Height of GopBlt/BmpImage in pixels
318 @param[out] PixelWidth Width of GopBlt/BmpImage in pixels
319
320 @retval EFI_SUCCESS GopBlt and GopBltSize are returned.
321 @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image
322 @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.
323 GopBltSize will contain the required size.
324 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.
325
326 **/
327 STATIC
328 EFI_STATUS
329 ConvertBmpToGopBlt (
330 IN VOID *BmpImage,
331 IN UINTN BmpImageSize,
332 IN OUT VOID **GopBlt,
333 IN OUT UINTN *GopBltSize,
334 OUT UINTN *PixelHeight,
335 OUT UINTN *PixelWidth
336 )
337 {
338 UINT8 *Image;
339 UINT8 *ImageHeader;
340 BMP_IMAGE_HEADER *BmpHeader;
341 BMP_COLOR_MAP *BmpColorMap;
342 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
343 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
344 UINT64 BltBufferSize;
345 UINTN Index;
346 UINTN Height;
347 UINTN Width;
348 UINTN ImageIndex;
349 UINT32 DataSizePerLine;
350 BOOLEAN IsAllocated;
351 UINT32 ColorMapNum;
352
353 if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {
354 return EFI_INVALID_PARAMETER;
355 }
356
357 BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;
358
359 if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
360 return EFI_UNSUPPORTED;
361 }
362
363 //
364 // Doesn't support compress.
365 //
366 if (BmpHeader->CompressionType != 0) {
367 return EFI_UNSUPPORTED;
368 }
369
370 //
371 // Only support BITMAPINFOHEADER format.
372 // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER
373 //
374 if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {
375 return EFI_UNSUPPORTED;
376 }
377
378 //
379 // The data size in each line must be 4 byte alignment.
380 //
381 DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);
382 BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);
383 if (BltBufferSize > (UINT32) ~0) {
384 return EFI_INVALID_PARAMETER;
385 }
386
387 if ((BmpHeader->Size != BmpImageSize) ||
388 (BmpHeader->Size < BmpHeader->ImageOffset) ||
389 (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {
390 return EFI_INVALID_PARAMETER;
391 }
392
393 //
394 // Calculate Color Map offset in the image.
395 //
396 Image = BmpImage;
397 BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));
398 if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {
399 return EFI_INVALID_PARAMETER;
400 }
401
402 if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {
403 switch (BmpHeader->BitPerPixel) {
404 case 1:
405 ColorMapNum = 2;
406 break;
407 case 4:
408 ColorMapNum = 16;
409 break;
410 case 8:
411 ColorMapNum = 256;
412 break;
413 default:
414 ColorMapNum = 0;
415 break;
416 }
417 //
418 // BMP file may has padding data between the bmp header section and the bmp data section.
419 //
420 if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {
421 return EFI_INVALID_PARAMETER;
422 }
423 }
424
425 //
426 // Calculate graphics image data address in the image
427 //
428 Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;
429 ImageHeader = Image;
430
431 //
432 // Calculate the BltBuffer needed size.
433 //
434 BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);
435 //
436 // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
437 //
438 if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {
439 return EFI_UNSUPPORTED;
440 }
441 BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
442
443 IsAllocated = FALSE;
444 if (*GopBlt == NULL) {
445 //
446 // GopBlt is not allocated by caller.
447 //
448 *GopBltSize = (UINTN) BltBufferSize;
449 *GopBlt = AllocatePool (*GopBltSize);
450 IsAllocated = TRUE;
451 if (*GopBlt == NULL) {
452 return EFI_OUT_OF_RESOURCES;
453 }
454 } else {
455 //
456 // GopBlt has been allocated by caller.
457 //
458 if (*GopBltSize < (UINTN) BltBufferSize) {
459 *GopBltSize = (UINTN) BltBufferSize;
460 return EFI_BUFFER_TOO_SMALL;
461 }
462 }
463
464 *PixelWidth = BmpHeader->PixelWidth;
465 *PixelHeight = BmpHeader->PixelHeight;
466
467 //
468 // Convert image from BMP to Blt buffer format
469 //
470 BltBuffer = *GopBlt;
471 for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {
472 Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];
473 for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {
474 switch (BmpHeader->BitPerPixel) {
475 case 1:
476 //
477 // Convert 1-bit (2 colors) BMP to 24-bit color
478 //
479 for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {
480 Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;
481 Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;
482 Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;
483 Blt++;
484 Width++;
485 }
486
487 Blt--;
488 Width--;
489 break;
490
491 case 4:
492 //
493 // Convert 4-bit (16 colors) BMP Palette to 24-bit color
494 //
495 Index = (*Image) >> 4;
496 Blt->Red = BmpColorMap[Index].Red;
497 Blt->Green = BmpColorMap[Index].Green;
498 Blt->Blue = BmpColorMap[Index].Blue;
499 if (Width < (BmpHeader->PixelWidth - 1)) {
500 Blt++;
501 Width++;
502 Index = (*Image) & 0x0f;
503 Blt->Red = BmpColorMap[Index].Red;
504 Blt->Green = BmpColorMap[Index].Green;
505 Blt->Blue = BmpColorMap[Index].Blue;
506 }
507 break;
508
509 case 8:
510 //
511 // Convert 8-bit (256 colors) BMP Palette to 24-bit color
512 //
513 Blt->Red = BmpColorMap[*Image].Red;
514 Blt->Green = BmpColorMap[*Image].Green;
515 Blt->Blue = BmpColorMap[*Image].Blue;
516 break;
517
518 case 24:
519 //
520 // It is 24-bit BMP.
521 //
522 Blt->Blue = *Image++;
523 Blt->Green = *Image++;
524 Blt->Red = *Image;
525 break;
526
527 case 32:
528 //
529 // it is 32-bit BMP. Skip pixel's highest byte
530 //
531 Blt->Blue = *Image++;
532 Blt->Green = *Image++;
533 Blt->Red = *Image++;
534 break;
535
536 default:
537 //
538 // Other bit format BMP is not supported.
539 //
540 if (IsAllocated) {
541 FreePool (*GopBlt);
542 *GopBlt = NULL;
543 }
544 return EFI_UNSUPPORTED;
545 };
546
547 }
548
549 ImageIndex = (UINTN) Image - (UINTN) ImageHeader;
550 if ((ImageIndex % 4) != 0) {
551 //
552 // Bmp Image starts each row on a 32-bit boundary!
553 //
554 Image = Image + (4 - (ImageIndex % 4));
555 }
556 }
557
558 return EFI_SUCCESS;
559 }
560
561
562 /**
563 Those capsules supported by the firmwares.
564
565 Caution: This function may receive untrusted input.
566
567 @param[in] CapsuleHeader Points to a capsule header.
568
569 @retval EFI_SUCESS Input capsule is supported by firmware.
570 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
571 **/
572 EFI_STATUS
573 DisplayCapsuleImage (
574 IN EFI_CAPSULE_HEADER *CapsuleHeader
575 )
576 {
577 DISPLAY_DISPLAY_PAYLOAD *ImagePayload;
578 UINTN PayloadSize;
579 EFI_STATUS Status;
580 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
581 UINTN BltSize;
582 UINTN Height;
583 UINTN Width;
584 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
585
586 ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1);
587 PayloadSize = CapsuleHeader->CapsuleImageSize - sizeof(EFI_CAPSULE_HEADER);
588
589 if (ImagePayload->Version != 1) {
590 return EFI_UNSUPPORTED;
591 }
592 if (CalculateCheckSum8((UINT8 *)CapsuleHeader, CapsuleHeader->CapsuleImageSize) != 0) {
593 return EFI_UNSUPPORTED;
594 }
595 //
596 // Only Support Bitmap by now
597 //
598 if (ImagePayload->ImageType != 0) {
599 return EFI_UNSUPPORTED;
600 }
601
602 //
603 // Try to open GOP
604 //
605 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
606 if (EFI_ERROR (Status)) {
607 Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&GraphicsOutput);
608 if (EFI_ERROR(Status)) {
609 return EFI_UNSUPPORTED;
610 }
611 }
612
613 if (GraphicsOutput->Mode->Mode != ImagePayload->Mode) {
614 return EFI_UNSUPPORTED;
615 }
616
617 Blt = NULL;
618 Width = 0;
619 Height = 0;
620 Status = ConvertBmpToGopBlt (
621 ImagePayload + 1,
622 PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),
623 (VOID **)&Blt,
624 &BltSize,
625 &Height,
626 &Width
627 );
628
629 if (EFI_ERROR (Status)) {
630 return Status;
631 }
632
633 Status = GraphicsOutput->Blt (
634 GraphicsOutput,
635 Blt,
636 EfiBltBufferToVideo,
637 0,
638 0,
639 (UINTN) ImagePayload->OffsetX,
640 (UINTN) ImagePayload->OffsetY,
641 Width,
642 Height,
643 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
644 );
645
646 FreePool(Blt);
647
648 return Status;
649 }
650
651 /**
652 Dump FMP information.
653
654 @param[in] ImageInfoSize The size of ImageInfo, in bytes.
655 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.
656 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
657 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.
658 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.
659 @param[in] PackageVersion The version of package.
660 @param[in] PackageVersionName The version name of package.
661 **/
662 VOID
663 DumpFmpImageInfo (
664 IN UINTN ImageInfoSize,
665 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
666 IN UINT32 DescriptorVersion,
667 IN UINT8 DescriptorCount,
668 IN UINTN DescriptorSize,
669 IN UINT32 PackageVersion,
670 IN CHAR16 *PackageVersionName
671 )
672 {
673 EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo;
674 UINTN Index;
675
676 DEBUG((DEBUG_VERBOSE, " DescriptorVersion - 0x%x\n", DescriptorVersion));
677 DEBUG((DEBUG_VERBOSE, " DescriptorCount - 0x%x\n", DescriptorCount));
678 DEBUG((DEBUG_VERBOSE, " DescriptorSize - 0x%x\n", DescriptorSize));
679 DEBUG((DEBUG_VERBOSE, " PackageVersion - 0x%x\n", PackageVersion));
680 DEBUG((DEBUG_VERBOSE, " PackageVersionName - %s\n\n", PackageVersionName));
681 CurrentImageInfo = ImageInfo;
682 for (Index = 0; Index < DescriptorCount; Index++) {
683 DEBUG((DEBUG_VERBOSE, " ImageDescriptor (%d)\n", Index));
684 DEBUG((DEBUG_VERBOSE, " ImageIndex - 0x%x\n", CurrentImageInfo->ImageIndex));
685 DEBUG((DEBUG_VERBOSE, " ImageTypeId - %g\n", &CurrentImageInfo->ImageTypeId));
686 DEBUG((DEBUG_VERBOSE, " ImageId - 0x%lx\n", CurrentImageInfo->ImageId));
687 DEBUG((DEBUG_VERBOSE, " ImageIdName - %s\n", CurrentImageInfo->ImageIdName));
688 DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", CurrentImageInfo->Version));
689 DEBUG((DEBUG_VERBOSE, " VersionName - %s\n", CurrentImageInfo->VersionName));
690 DEBUG((DEBUG_VERBOSE, " Size - 0x%x\n", CurrentImageInfo->Size));
691 DEBUG((DEBUG_VERBOSE, " AttributesSupported - 0x%lx\n", CurrentImageInfo->AttributesSupported));
692 DEBUG((DEBUG_VERBOSE, " AttributesSetting - 0x%lx\n", CurrentImageInfo->AttributesSetting));
693 DEBUG((DEBUG_VERBOSE, " Compatibilities - 0x%lx\n", CurrentImageInfo->Compatibilities));
694 if (DescriptorVersion > 1) {
695 DEBUG((DEBUG_VERBOSE, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion));
696 if (DescriptorVersion > 2) {
697 DEBUG((DEBUG_VERBOSE, " LastAttemptVersion - 0x%x\n", CurrentImageInfo->LastAttemptVersion));
698 DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", CurrentImageInfo->LastAttemptStatus));
699 DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", CurrentImageInfo->HardwareInstance));
700 }
701 }
702 //
703 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
704 //
705 CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);
706 }
707 }
708
709 /**
710 Dump a non-nested FMP capsule.
711
712 @param[in] CapsuleHeader A pointer to CapsuleHeader
713 **/
714 VOID
715 DumpFmpCapsule (
716 IN EFI_CAPSULE_HEADER *CapsuleHeader
717 )
718 {
719 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
720 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
721 UINTN Index;
722 UINT64 *ItemOffsetList;
723
724 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
725
726 DEBUG((DEBUG_VERBOSE, "FmpCapsule:\n"));
727 DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", FmpCapsuleHeader->Version));
728 DEBUG((DEBUG_VERBOSE, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount));
729 DEBUG((DEBUG_VERBOSE, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader->PayloadItemCount));
730
731 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
732 for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
733 DEBUG((DEBUG_VERBOSE, " ItemOffsetList[%d] - 0x%lx\n", Index, ItemOffsetList[Index]));
734 }
735 for (; Index < (UINT32)FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; Index++) {
736 DEBUG((DEBUG_VERBOSE, " ItemOffsetList[%d] - 0x%lx\n", Index, ItemOffsetList[Index]));
737 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
738
739 DEBUG((DEBUG_VERBOSE, " ImageHeader:\n"));
740 DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", ImageHeader->Version));
741 DEBUG((DEBUG_VERBOSE, " UpdateImageTypeId - %g\n", &ImageHeader->UpdateImageTypeId));
742 DEBUG((DEBUG_VERBOSE, " UpdateImageIndex - 0x%x\n", ImageHeader->UpdateImageIndex));
743 DEBUG((DEBUG_VERBOSE, " UpdateImageSize - 0x%x\n", ImageHeader->UpdateImageSize));
744 DEBUG((DEBUG_VERBOSE, " UpdateVendorCodeSize - 0x%x\n", ImageHeader->UpdateVendorCodeSize));
745 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
746 DEBUG((DEBUG_VERBOSE, " UpdateHardwareInstance - 0x%lx\n", ImageHeader->UpdateHardwareInstance));
747 }
748 }
749 }
750
751 /**
752 Dump all FMP information.
753 **/
754 VOID
755 DumpAllFmpInfo (
756 VOID
757 )
758 {
759 EFI_STATUS Status;
760 EFI_HANDLE *HandleBuffer;
761 UINTN NumberOfHandles;
762 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
763 UINTN Index;
764 UINTN ImageInfoSize;
765 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
766 UINT32 FmpImageInfoDescriptorVer;
767 UINT8 FmpImageInfoCount;
768 UINTN DescriptorSize;
769 UINT32 PackageVersion;
770 CHAR16 *PackageVersionName;
771
772 Status = gBS->LocateHandleBuffer (
773 ByProtocol,
774 &gEfiFirmwareManagementProtocolGuid,
775 NULL,
776 &NumberOfHandles,
777 &HandleBuffer
778 );
779 if (EFI_ERROR(Status)) {
780 return ;
781 }
782
783 for (Index = 0; Index < NumberOfHandles; Index++) {
784 Status = gBS->HandleProtocol(
785 HandleBuffer[Index],
786 &gEfiFirmwareManagementProtocolGuid,
787 (VOID **)&Fmp
788 );
789 if (EFI_ERROR(Status)) {
790 continue;
791 }
792
793 ImageInfoSize = 0;
794 Status = Fmp->GetImageInfo (
795 Fmp,
796 &ImageInfoSize,
797 NULL,
798 NULL,
799 NULL,
800 NULL,
801 NULL,
802 NULL
803 );
804 if (Status != EFI_BUFFER_TOO_SMALL) {
805 continue;
806 }
807
808 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
809 if (FmpImageInfoBuf == NULL) {
810 continue;
811 }
812
813 PackageVersionName = NULL;
814 Status = Fmp->GetImageInfo (
815 Fmp,
816 &ImageInfoSize, // ImageInfoSize
817 FmpImageInfoBuf, // ImageInfo
818 &FmpImageInfoDescriptorVer, // DescriptorVersion
819 &FmpImageInfoCount, // DescriptorCount
820 &DescriptorSize, // DescriptorSize
821 &PackageVersion, // PackageVersion
822 &PackageVersionName // PackageVersionName
823 );
824 if (EFI_ERROR(Status)) {
825 FreePool(FmpImageInfoBuf);
826 continue;
827 }
828
829 DEBUG((DEBUG_INFO, "FMP (%d) ImageInfo:\n", Index));
830 DumpFmpImageInfo(
831 ImageInfoSize, // ImageInfoSize
832 FmpImageInfoBuf, // ImageInfo
833 FmpImageInfoDescriptorVer, // DescriptorVersion
834 FmpImageInfoCount, // DescriptorCount
835 DescriptorSize, // DescriptorSize
836 PackageVersion, // PackageVersion
837 PackageVersionName // PackageVersionName
838 );
839
840 if (PackageVersionName != NULL) {
841 FreePool(PackageVersionName);
842 }
843
844 FreePool(FmpImageInfoBuf);
845 }
846
847 return ;
848 }
849
850 /**
851 Get FMP handle by ImageTypeId and HardwareInstance.
852
853 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
854 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
855 @param[in,out] NoHandles The number of handles returned in Buffer.
856 @param[out] Buffer[out] A pointer to the buffer to return the requested array of handles.
857
858 @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
859 handles in Buffer was returned in NoHandles.
860 @retval EFI_NOT_FOUND No handles match the search.
861 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
862 **/
863 EFI_STATUS
864 GetFmpHandleBufferByType (
865 IN EFI_GUID *UpdateImageTypeId,
866 IN UINT64 UpdateHardwareInstance,
867 IN OUT UINTN *NoHandles,
868 OUT EFI_HANDLE **Buffer
869 )
870 {
871 EFI_STATUS Status;
872 EFI_HANDLE *HandleBuffer;
873 UINTN NumberOfHandles;
874 EFI_HANDLE *MatchedHandleBuffer;
875 UINTN MatchedNumberOfHandles;
876 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
877 UINTN Index;
878 UINTN ImageInfoSize;
879 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
880 UINT32 FmpImageInfoDescriptorVer;
881 UINT8 FmpImageInfoCount;
882 UINTN DescriptorSize;
883 UINT32 PackageVersion;
884 CHAR16 *PackageVersionName;
885 UINTN Index2;
886 EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;
887
888 *NoHandles = 0;
889 *Buffer = NULL;
890
891 Status = gBS->LocateHandleBuffer (
892 ByProtocol,
893 &gEfiFirmwareManagementProtocolGuid,
894 NULL,
895 &NumberOfHandles,
896 &HandleBuffer
897 );
898 if (EFI_ERROR(Status)) {
899 return Status;
900 }
901
902 MatchedNumberOfHandles = 0;
903 MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles);
904 if (MatchedHandleBuffer == NULL) {
905 FreePool (HandleBuffer);
906 return EFI_OUT_OF_RESOURCES;
907 }
908
909 for (Index = 0; Index < NumberOfHandles; Index++) {
910 Status = gBS->HandleProtocol(
911 HandleBuffer[Index],
912 &gEfiFirmwareManagementProtocolGuid,
913 (VOID **)&Fmp
914 );
915 if (EFI_ERROR(Status)) {
916 continue;
917 }
918
919 ImageInfoSize = 0;
920 Status = Fmp->GetImageInfo (
921 Fmp,
922 &ImageInfoSize,
923 NULL,
924 NULL,
925 NULL,
926 NULL,
927 NULL,
928 NULL
929 );
930 if (Status != EFI_BUFFER_TOO_SMALL) {
931 continue;
932 }
933
934 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
935 if (FmpImageInfoBuf == NULL) {
936 continue;
937 }
938
939 PackageVersionName = NULL;
940 Status = Fmp->GetImageInfo (
941 Fmp,
942 &ImageInfoSize, // ImageInfoSize
943 FmpImageInfoBuf, // ImageInfo
944 &FmpImageInfoDescriptorVer, // DescriptorVersion
945 &FmpImageInfoCount, // DescriptorCount
946 &DescriptorSize, // DescriptorSize
947 &PackageVersion, // PackageVersion
948 &PackageVersionName // PackageVersionName
949 );
950 if (EFI_ERROR(Status)) {
951 FreePool(FmpImageInfoBuf);
952 continue;
953 }
954
955 if (PackageVersionName != NULL) {
956 FreePool(PackageVersionName);
957 }
958
959 TempFmpImageInfo = FmpImageInfoBuf;
960 for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
961 //
962 // Check if this FMP instance matches
963 //
964 if (CompareGuid(UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId)) {
965 if ((UpdateHardwareInstance == 0) ||
966 ((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) &&
967 (UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance))) {
968 MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];
969 MatchedNumberOfHandles++;
970 break;
971 }
972 }
973 TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
974 }
975 FreePool(FmpImageInfoBuf);
976 }
977
978 if (MatchedNumberOfHandles == 0) {
979 return EFI_NOT_FOUND;
980 }
981
982 *NoHandles = MatchedNumberOfHandles;
983 *Buffer = MatchedHandleBuffer;
984
985 return EFI_SUCCESS;
986 }
987
988 /**
989 Return FmpImageInfoDescriptorVer by an FMP handle.
990
991 @param[in] Handle A FMP handle.
992
993 @return FmpImageInfoDescriptorVer associated with the FMP.
994 **/
995 UINT32
996 GetFmpImageInfoDescriptorVer (
997 IN EFI_HANDLE Handle
998 )
999 {
1000 EFI_STATUS Status;
1001 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
1002 UINTN ImageInfoSize;
1003 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
1004 UINT32 FmpImageInfoDescriptorVer;
1005 UINT8 FmpImageInfoCount;
1006 UINTN DescriptorSize;
1007 UINT32 PackageVersion;
1008 CHAR16 *PackageVersionName;
1009
1010 Status = gBS->HandleProtocol(
1011 Handle,
1012 &gEfiFirmwareManagementProtocolGuid,
1013 (VOID **)&Fmp
1014 );
1015 if (EFI_ERROR(Status)) {
1016 return 0;
1017 }
1018
1019 ImageInfoSize = 0;
1020 Status = Fmp->GetImageInfo (
1021 Fmp,
1022 &ImageInfoSize,
1023 NULL,
1024 NULL,
1025 NULL,
1026 NULL,
1027 NULL,
1028 NULL
1029 );
1030 if (Status != EFI_BUFFER_TOO_SMALL) {
1031 return 0;
1032 }
1033
1034 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
1035 if (FmpImageInfoBuf == NULL) {
1036 return 0;
1037 }
1038
1039 PackageVersionName = NULL;
1040 Status = Fmp->GetImageInfo (
1041 Fmp,
1042 &ImageInfoSize, // ImageInfoSize
1043 FmpImageInfoBuf, // ImageInfo
1044 &FmpImageInfoDescriptorVer, // DescriptorVersion
1045 &FmpImageInfoCount, // DescriptorCount
1046 &DescriptorSize, // DescriptorSize
1047 &PackageVersion, // PackageVersion
1048 &PackageVersionName // PackageVersionName
1049 );
1050 if (EFI_ERROR(Status)) {
1051 FreePool(FmpImageInfoBuf);
1052 return 0;
1053 }
1054 return FmpImageInfoDescriptorVer;
1055 }
1056
1057 /**
1058 Set FMP image data.
1059
1060 @param[in] Handle A FMP handle.
1061 @param[in] ImageHeader The payload image header.
1062 @param[in] PayloadIndex The index of the payload.
1063
1064 @return The status of FMP->SetImage.
1065 **/
1066 EFI_STATUS
1067 SetFmpImageData (
1068 IN EFI_HANDLE Handle,
1069 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
1070 IN UINTN PayloadIndex
1071 )
1072 {
1073 EFI_STATUS Status;
1074 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
1075 UINT8 *Image;
1076 VOID *VendorCode;
1077 CHAR16 *AbortReason;
1078
1079 Status = gBS->HandleProtocol(
1080 Handle,
1081 &gEfiFirmwareManagementProtocolGuid,
1082 (VOID **)&Fmp
1083 );
1084 if (EFI_ERROR(Status)) {
1085 return Status;
1086 }
1087
1088 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
1089 Image = (UINT8 *)(ImageHeader + 1);
1090 } else {
1091 //
1092 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
1093 // Header should exclude UpdateHardwareInstance field
1094 //
1095 Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
1096 }
1097
1098 if (ImageHeader->UpdateVendorCodeSize == 0) {
1099 VendorCode = NULL;
1100 } else {
1101 VendorCode = Image + ImageHeader->UpdateImageSize;
1102 }
1103 AbortReason = NULL;
1104 DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));
1105 DEBUG((DEBUG_INFO, "ImageTypeId - %g, ", &ImageHeader->UpdateImageTypeId));
1106 DEBUG((DEBUG_INFO, "PayloadIndex - 0x%x, ", PayloadIndex));
1107 DEBUG((DEBUG_INFO, "ImageIndex - 0x%x ", ImageHeader->UpdateImageIndex));
1108 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
1109 DEBUG((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));
1110 }
1111 DEBUG((DEBUG_INFO, "\n"));
1112 Status = Fmp->SetImage(
1113 Fmp,
1114 ImageHeader->UpdateImageIndex, // ImageIndex
1115 Image, // Image
1116 ImageHeader->UpdateImageSize, // ImageSize
1117 VendorCode, // VendorCode
1118 Update_Image_Progress, // Progress
1119 &AbortReason // AbortReason
1120 );
1121 DEBUG((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));
1122 if (AbortReason != NULL) {
1123 DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));
1124 FreePool(AbortReason);
1125 }
1126
1127 return Status;
1128 }
1129
1130 /**
1131 Start a UEFI image in the FMP payload.
1132
1133 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
1134 @param[in] ImageSize The size in bytes of ImageBuffer.
1135
1136 @return The status of gBS->LoadImage and gBS->StartImage.
1137 **/
1138 EFI_STATUS
1139 StartFmpImage (
1140 IN VOID *ImageBuffer,
1141 IN UINTN ImageSize
1142 )
1143 {
1144 MEMMAP_DEVICE_PATH MemMapNode;
1145 EFI_STATUS Status;
1146 EFI_HANDLE ImageHandle;
1147 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;
1148 UINTN ExitDataSize;
1149
1150 SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));
1151 MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;
1152 MemMapNode.Header.SubType = HW_MEMMAP_DP;
1153 MemMapNode.MemoryType = EfiBootServicesCode;
1154 MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBuffer;
1155 MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)ImageBuffer + ImageSize - 1);
1156
1157 DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
1158 if (DriverDevicePath == NULL) {
1159 return EFI_OUT_OF_RESOURCES;
1160 }
1161
1162 DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));
1163 Status = gBS->LoadImage(
1164 FALSE,
1165 gImageHandle,
1166 DriverDevicePath,
1167 ImageBuffer,
1168 ImageSize,
1169 &ImageHandle
1170 );
1171 DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));
1172 if (EFI_ERROR(Status)) {
1173 FreePool(DriverDevicePath);
1174 return Status;
1175 }
1176
1177 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));
1178 Status = gBS->StartImage(
1179 ImageHandle,
1180 &ExitDataSize,
1181 NULL
1182 );
1183 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));
1184 if (EFI_ERROR(Status)) {
1185 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
1186 }
1187
1188 FreePool(DriverDevicePath);
1189 return Status;
1190 }
1191
1192 /**
1193 Record FMP capsule status.
1194
1195 @param[in] Handle A FMP handle.
1196 @param[in] CapsuleHeader The capsule image header
1197 @param[in] CapsuleStatus The capsule process stauts
1198 @param[in] PayloadIndex FMP payload index
1199 @param[in] ImageHeader FMP image header
1200 **/
1201 VOID
1202 RecordFmpCapsuleStatus (
1203 IN EFI_HANDLE Handle, OPTIONAL
1204 IN EFI_CAPSULE_HEADER *CapsuleHeader,
1205 IN EFI_STATUS CapsuleStatus,
1206 IN UINTN PayloadIndex,
1207 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
1208 )
1209 {
1210 EFI_STATUS Status;
1211 EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath;
1212 UINT32 FmpImageInfoDescriptorVer;
1213 EFI_STATUS StatusEsrt;
1214 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
1215 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
1216
1217 FmpDevicePath = NULL;
1218 if (Handle != NULL) {
1219 gBS->HandleProtocol(
1220 Handle,
1221 &gEfiDevicePathProtocolGuid,
1222 (VOID **)&FmpDevicePath
1223 );
1224 }
1225
1226 RecordFmpCapsuleStatusVariable (
1227 CapsuleHeader,
1228 CapsuleStatus,
1229 PayloadIndex,
1230 ImageHeader,
1231 FmpDevicePath
1232 );
1233
1234 //
1235 // Update corresponding ESRT entry LastAttemp Status
1236 //
1237 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
1238 if (EFI_ERROR (Status)) {
1239 return ;
1240 }
1241
1242 if (Handle == NULL) {
1243 return ;
1244 }
1245
1246 //
1247 // Update EsrtEntry For V1, V2 FMP instance.
1248 // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
1249 //
1250 FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);
1251 if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {
1252 StatusEsrt = EsrtProtocol->GetEsrtEntry(&ImageHeader->UpdateImageTypeId, &EsrtEntry);
1253 if (!EFI_ERROR(StatusEsrt)){
1254 if (!EFI_ERROR(CapsuleStatus)) {
1255 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
1256 } else {
1257 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
1258 }
1259 EsrtEntry.LastAttemptVersion = 0;
1260 EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
1261 }
1262 }
1263 }
1264
1265 /**
1266 Process Firmware management protocol data capsule.
1267
1268 This function assumes the caller validated the capsule by using
1269 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1270 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1271 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1272
1273 This function need support nested FMP capsule.
1274
1275 @param[in] CapsuleHeader Points to a capsule header.
1276
1277 @retval EFI_SUCESS Process Capsule Image successfully.
1278 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1279 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1280 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1281 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1282 **/
1283 EFI_STATUS
1284 ProcessFmpCapsuleImage (
1285 IN EFI_CAPSULE_HEADER *CapsuleHeader
1286 )
1287 {
1288 EFI_STATUS Status;
1289 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
1290 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
1291 UINT64 *ItemOffsetList;
1292 UINT32 ItemNum;
1293 UINTN Index;
1294 EFI_HANDLE *HandleBuffer;
1295 UINTN NumberOfHandles;
1296 UINTN DriverLen;
1297 UINT64 UpdateHardwareInstance;
1298 UINTN Index2;
1299 BOOLEAN NotReady;
1300 BOOLEAN Abort;
1301
1302 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
1303 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));
1304 }
1305
1306 NotReady = FALSE;
1307 Abort = FALSE;
1308
1309 DumpFmpCapsule(CapsuleHeader);
1310
1311 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
1312
1313 if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
1314 return EFI_INVALID_PARAMETER;
1315 }
1316 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
1317
1318 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
1319
1320 //
1321 // capsule in which driver count and payload count are both zero is not processed.
1322 //
1323 if (ItemNum == 0) {
1324 return EFI_SUCCESS;
1325 }
1326
1327 //
1328 // 1. Try to load & start all the drivers within capsule
1329 //
1330 for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
1331 if ((FmpCapsuleHeader->PayloadItemCount == 0) &&
1332 (Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1)) {
1333 //
1334 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1335 //
1336 DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];
1337 } else {
1338 DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];
1339 }
1340
1341 Status = StartFmpImage (
1342 (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
1343 DriverLen
1344 );
1345 if (EFI_ERROR(Status)) {
1346 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
1347 return Status;
1348 }
1349 }
1350
1351 //
1352 // 2. Route payload to right FMP instance
1353 //
1354 DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));
1355
1356 DumpAllFmpInfo ();
1357
1358 //
1359 // Check all the payload entry in capsule payload list
1360 //
1361 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
1362 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
1363
1364 UpdateHardwareInstance = 0;
1365 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
1366 UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;
1367 }
1368
1369 Status = GetFmpHandleBufferByType (
1370 &ImageHeader->UpdateImageTypeId,
1371 UpdateHardwareInstance,
1372 &NumberOfHandles,
1373 &HandleBuffer
1374 );
1375 if (EFI_ERROR(Status)) {
1376 NotReady = TRUE;
1377 RecordFmpCapsuleStatus (
1378 NULL,
1379 CapsuleHeader,
1380 EFI_NOT_READY,
1381 Index - FmpCapsuleHeader->EmbeddedDriverCount,
1382 ImageHeader
1383 );
1384 continue;
1385 }
1386
1387 for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {
1388 if (Abort) {
1389 RecordFmpCapsuleStatus (
1390 HandleBuffer[Index2],
1391 CapsuleHeader,
1392 EFI_ABORTED,
1393 Index - FmpCapsuleHeader->EmbeddedDriverCount,
1394 ImageHeader
1395 );
1396 continue;
1397 }
1398
1399 Status = SetFmpImageData (
1400 HandleBuffer[Index2],
1401 ImageHeader,
1402 Index - FmpCapsuleHeader->EmbeddedDriverCount
1403 );
1404 if (Status != EFI_SUCCESS) {
1405 Abort = TRUE;
1406 }
1407
1408 RecordFmpCapsuleStatus (
1409 HandleBuffer[Index2],
1410 CapsuleHeader,
1411 Status,
1412 Index - FmpCapsuleHeader->EmbeddedDriverCount,
1413 ImageHeader
1414 );
1415 }
1416 if (HandleBuffer != NULL) {
1417 FreePool(HandleBuffer);
1418 }
1419 }
1420
1421 if (NotReady) {
1422 return EFI_NOT_READY;
1423 }
1424
1425 //
1426 // always return SUCCESS to indicate this capsule is processed.
1427 // The status of SetImage is recorded in capsule result variable.
1428 //
1429 return EFI_SUCCESS;
1430 }
1431
1432 /**
1433 Return if there is a FMP header below capsule header.
1434
1435 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1436
1437 @retval TRUE There is a FMP header below capsule header.
1438 @retval FALSE There is not a FMP header below capsule header
1439 **/
1440 BOOLEAN
1441 IsNestedFmpCapsule (
1442 IN EFI_CAPSULE_HEADER *CapsuleHeader
1443 )
1444 {
1445 EFI_STATUS Status;
1446 EFI_SYSTEM_RESOURCE_TABLE *Esrt;
1447 EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
1448 UINTN Index;
1449 BOOLEAN EsrtGuidFound;
1450 EFI_CAPSULE_HEADER *NestedCapsuleHeader;
1451 UINTN NestedCapsuleSize;
1452 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
1453 EFI_SYSTEM_RESOURCE_ENTRY Entry;
1454
1455 EsrtGuidFound = FALSE;
1456 if (mIsVirtualAddrConverted) {
1457 if(mEsrtTable != NULL) {
1458 EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);
1459 for (Index = 0; Index < mEsrtTable->FwResourceCount ; Index++, EsrtEntry++) {
1460 if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
1461 EsrtGuidFound = TRUE;
1462 break;
1463 }
1464 }
1465 }
1466 } else {
1467 //
1468 // Check ESRT protocol
1469 //
1470 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
1471 if (!EFI_ERROR(Status)) {
1472 Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);
1473 if (!EFI_ERROR(Status)) {
1474 EsrtGuidFound = TRUE;
1475 }
1476 }
1477
1478 //
1479 // Check ESRT configuration table
1480 //
1481 if (!EsrtGuidFound) {
1482 Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
1483 if (!EFI_ERROR(Status)) {
1484 ASSERT (Esrt != NULL);
1485 EsrtEntry = (VOID *)(Esrt + 1);
1486 for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
1487 if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
1488 EsrtGuidFound = TRUE;
1489 break;
1490 }
1491 }
1492 }
1493 }
1494 }
1495 if (!EsrtGuidFound) {
1496 return FALSE;
1497 }
1498
1499 //
1500 // Check nested capsule header
1501 // FMP GUID after ESRT one
1502 //
1503 NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
1504 NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;
1505 if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
1506 return FALSE;
1507 }
1508 if (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {
1509 return FALSE;
1510 }
1511 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {
1512 return FALSE;
1513 }
1514 DEBUG ((DEBUG_INFO, "IsNestedFmpCapsule\n"));
1515 return TRUE;
1516 }
1517
1518 /**
1519 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1520
1521 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1522
1523 @retval TRUE It is a system FMP.
1524 @retval FALSE It is a device FMP.
1525 **/
1526 BOOLEAN
1527 IsFmpCapsule (
1528 IN EFI_CAPSULE_HEADER *CapsuleHeader
1529 )
1530 {
1531 if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
1532 return TRUE;
1533 }
1534 if (IsNestedFmpCapsule(CapsuleHeader)) {
1535 return TRUE;
1536 }
1537 return FALSE;
1538 }
1539
1540 /**
1541 Those capsules supported by the firmwares.
1542
1543 Caution: This function may receive untrusted input.
1544
1545 @param[in] CapsuleHeader Points to a capsule header.
1546
1547 @retval EFI_SUCESS Input capsule is supported by firmware.
1548 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1549 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1550 **/
1551 EFI_STATUS
1552 EFIAPI
1553 SupportCapsuleImage (
1554 IN EFI_CAPSULE_HEADER *CapsuleHeader
1555 )
1556 {
1557 //
1558 // check Display Capsule Guid
1559 //
1560 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
1561 return EFI_SUCCESS;
1562 }
1563
1564 if (IsFmpCapsule(CapsuleHeader)) {
1565 //
1566 // Check layout of FMP capsule
1567 //
1568 return ValidateFmpCapsule(CapsuleHeader, NULL);
1569 }
1570 DEBUG((DEBUG_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));
1571 return EFI_UNSUPPORTED;
1572 }
1573
1574 /**
1575 The firmware implements to process the capsule image.
1576
1577 Caution: This function may receive untrusted input.
1578
1579 @param[in] CapsuleHeader Points to a capsule header.
1580
1581 @retval EFI_SUCESS Process Capsule Image successfully.
1582 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1583 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1584 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1585 **/
1586 EFI_STATUS
1587 EFIAPI
1588 ProcessCapsuleImage (
1589 IN EFI_CAPSULE_HEADER *CapsuleHeader
1590 )
1591 {
1592 EFI_STATUS Status;
1593
1594 if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
1595 RecordCapsuleStatusVariable(CapsuleHeader, EFI_UNSUPPORTED);
1596 return EFI_UNSUPPORTED;
1597 }
1598
1599 //
1600 // Display image in firmware update display capsule
1601 //
1602 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
1603 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1604 Status = DisplayCapsuleImage(CapsuleHeader);
1605 RecordCapsuleStatusVariable(CapsuleHeader, Status);
1606 return Status;
1607 }
1608
1609 //
1610 // Check FMP capsule layout
1611 //
1612 if (IsFmpCapsule (CapsuleHeader)) {
1613 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
1614 DEBUG((DEBUG_INFO, "ValidateFmpCapsule ...\n"));
1615 Status = ValidateFmpCapsule(CapsuleHeader, NULL);
1616 DEBUG((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));
1617 if (EFI_ERROR(Status)) {
1618 RecordCapsuleStatusVariable(CapsuleHeader, Status);
1619 return Status;
1620 }
1621
1622 //
1623 // Press EFI FMP Capsule
1624 //
1625 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
1626 Status = ProcessFmpCapsuleImage(CapsuleHeader);
1627 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
1628
1629 return Status;
1630 }
1631
1632 return EFI_UNSUPPORTED;
1633 }
1634
1635 /**
1636 Callback function executed when the EndOfDxe event group is signaled.
1637
1638 @param[in] Event Event whose notification function is being invoked.
1639 @param[in] Context The pointer to the notification function's context, which
1640 is implementation-dependent.
1641 **/
1642 VOID
1643 EFIAPI
1644 DxeCapsuleLibEndOfDxe (
1645 IN EFI_EVENT Event,
1646 IN VOID *Context
1647 )
1648 {
1649 mDxeCapsuleLibEndOfDxe = TRUE;
1650 }
1651
1652 /**
1653 The constructor function.
1654
1655 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1656 @param[in] SystemTable A pointer to the EFI System Table.
1657
1658 @retval EFI_SUCCESS The constructor successfully .
1659 **/
1660 EFI_STATUS
1661 EFIAPI
1662 DxeCapsuleLibConstructor (
1663 IN EFI_HANDLE ImageHandle,
1664 IN EFI_SYSTEM_TABLE *SystemTable
1665 )
1666 {
1667 EFI_STATUS Status;
1668
1669 Status = gBS->CreateEventEx (
1670 EVT_NOTIFY_SIGNAL,
1671 TPL_CALLBACK,
1672 DxeCapsuleLibEndOfDxe,
1673 NULL,
1674 &gEfiEndOfDxeEventGroupGuid,
1675 &mDxeCapsuleLibEndOfDxeEvent
1676 );
1677 ASSERT_EFI_ERROR (Status);
1678
1679 InitCapsuleVariable();
1680
1681 return EFI_SUCCESS;
1682 }
1683
1684 /**
1685 The destructor function closes the End of DXE event.
1686
1687 @param ImageHandle The firmware allocated handle for the EFI image.
1688 @param SystemTable A pointer to the EFI System Table.
1689
1690 @retval EFI_SUCCESS The destructor completed successfully.
1691 **/
1692 EFI_STATUS
1693 EFIAPI
1694 DxeCapsuleLibDestructor (
1695 IN EFI_HANDLE ImageHandle,
1696 IN EFI_SYSTEM_TABLE *SystemTable
1697 )
1698 {
1699 EFI_STATUS Status;
1700
1701 //
1702 // Close the End of DXE event.
1703 //
1704 Status = gBS->CloseEvent (mDxeCapsuleLibEndOfDxeEvent);
1705 ASSERT_EFI_ERROR (Status);
1706
1707 return EFI_SUCCESS;
1708 }