]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/CapsulePei/Common/CapsuleCoalesce.c
MdeModulePkg/CapsulePei: Change debug MACRO
[mirror_edk2.git] / MdeModulePkg / Universal / CapsulePei / Common / CapsuleCoalesce.c
1 /** @file
2 The logic to process capsule.
3
4 Caution: This module requires additional review when modified.
5 This driver 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 CapsuleDataCoalesce() will do basic validation before coalesce capsule data
10 into memory.
11
12 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
13 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
14 SPDX-License-Identifier: BSD-2-Clause-Patent
15
16 **/
17
18 #include <Uefi.h>
19 #include <PiPei.h>
20
21 #include <Guid/CapsuleVendor.h>
22
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/DebugLib.h>
25 #include <Library/PrintLib.h>
26 #include <Library/BaseLib.h>
27
28 #include "CommonHeader.h"
29
30 #define MIN_COALESCE_ADDR (1024 * 1024)
31
32 /**
33 Given a pointer to the capsule block list, info on the available system
34 memory, and the size of a buffer, find a free block of memory where a
35 buffer of the given size can be copied to safely.
36
37 @param BlockList Pointer to head of capsule block descriptors
38 @param MemBase Pointer to the base of memory in which we want to find free space
39 @param MemSize The size of the block of memory pointed to by MemBase
40 @param DataSize How big a free block we want to find
41
42 @return A pointer to a memory block of at least DataSize that lies somewhere
43 between MemBase and (MemBase + MemSize). The memory pointed to does not
44 contain any of the capsule block descriptors or capsule blocks pointed to
45 by the BlockList.
46
47 **/
48 UINT8 *
49 FindFreeMem (
50 EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
51 UINT8 *MemBase,
52 UINTN MemSize,
53 UINTN DataSize
54 );
55
56 /**
57 The capsule block descriptors may be fragmented and spread all over memory.
58 To simplify the coalescing of capsule blocks, first coalesce all the
59 capsule block descriptors low in memory.
60
61 The descriptors passed in can be fragmented throughout memory. Here
62 they are relocated into memory to turn them into a contiguous (null
63 terminated) array.
64
65 @param PeiServices pointer to PEI services table
66 @param BlockList pointer to the capsule block descriptors
67 @param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
68 @param MemBase base of system memory in which we can work
69 @param MemSize size of the system memory pointed to by MemBase
70
71 @retval NULL could not relocate the descriptors
72 @retval Pointer to the base of the successfully-relocated block descriptors.
73
74 **/
75 EFI_CAPSULE_BLOCK_DESCRIPTOR *
76 RelocateBlockDescriptors (
77 IN EFI_PEI_SERVICES **PeiServices,
78 IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
79 IN UINTN NumDescriptors,
80 IN UINT8 *MemBase,
81 IN UINTN MemSize
82 );
83
84 /**
85 Check every capsule header.
86
87 @param CapsuleHeader The pointer to EFI_CAPSULE_HEADER
88
89 @retval FALSE Capsule is OK
90 @retval TRUE Capsule is corrupted
91
92 **/
93 BOOLEAN
94 IsCapsuleCorrupted (
95 IN EFI_CAPSULE_HEADER *CapsuleHeader
96 );
97
98 /**
99 Determine if two buffers overlap in memory.
100
101 @param Buff1 pointer to first buffer
102 @param Size1 size of Buff1
103 @param Buff2 pointer to second buffer
104 @param Size2 size of Buff2
105
106 @retval TRUE Buffers overlap in memory.
107 @retval FALSE Buffer doesn't overlap.
108
109 **/
110 BOOLEAN
111 IsOverlapped (
112 UINT8 *Buff1,
113 UINTN Size1,
114 UINT8 *Buff2,
115 UINTN Size2
116 );
117
118 /**
119 Given a pointer to a capsule block descriptor, traverse the list to figure
120 out how many legitimate descriptors there are, and how big the capsule it
121 refers to is.
122
123 @param Desc Pointer to the capsule block descriptors
124 @param NumDescriptors Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
125 @param CapsuleSize Optional pointer to where to return the capsule image size
126 @param CapsuleNumber Optional pointer to where to return the number of capsule
127
128 @retval EFI_NOT_FOUND No descriptors containing data in the list
129 @retval EFI_SUCCESS Return data is valid
130
131 **/
132 EFI_STATUS
133 GetCapsuleInfo (
134 IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc,
135 IN OUT UINTN *NumDescriptors OPTIONAL,
136 IN OUT UINTN *CapsuleSize OPTIONAL,
137 IN OUT UINTN *CapsuleNumber OPTIONAL
138 );
139
140 /**
141 Given a pointer to the capsule block list, info on the available system
142 memory, and the size of a buffer, find a free block of memory where a
143 buffer of the given size can be copied to safely.
144
145 @param BlockList Pointer to head of capsule block descriptors
146 @param MemBase Pointer to the base of memory in which we want to find free space
147 @param MemSize The size of the block of memory pointed to by MemBase
148 @param DataSize How big a free block we want to find
149
150 @return A pointer to a memory block of at least DataSize that lies somewhere
151 between MemBase and (MemBase + MemSize). The memory pointed to does not
152 contain any of the capsule block descriptors or capsule blocks pointed to
153 by the BlockList.
154
155 **/
156 UINT8 *
157 FindFreeMem (
158 EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
159 UINT8 *MemBase,
160 UINTN MemSize,
161 UINTN DataSize
162 )
163 {
164 UINTN Size;
165 EFI_CAPSULE_BLOCK_DESCRIPTOR *CurrDesc;
166 EFI_CAPSULE_BLOCK_DESCRIPTOR *TempDesc;
167 UINT8 *MemEnd;
168 BOOLEAN Failed;
169
170 //
171 // Need at least enough to copy the data to at the end of the buffer, so
172 // say the end is less the data size for easy comparisons here.
173 //
174 MemEnd = MemBase + MemSize - DataSize;
175 CurrDesc = BlockList;
176 //
177 // Go through all the descriptor blocks and see if any obstruct the range
178 //
179 while (CurrDesc != NULL) {
180 //
181 // Get the size of this block list and see if it's in the way
182 //
183 Failed = FALSE;
184 TempDesc = CurrDesc;
185 Size = sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
186 while (TempDesc->Length != 0) {
187 Size += sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
188 TempDesc++;
189 }
190
191 if (IsOverlapped (MemBase, DataSize, (UINT8 *) CurrDesc, Size)) {
192 //
193 // Set our new base to the end of this block list and start all over
194 //
195 MemBase = (UINT8 *) CurrDesc + Size;
196 CurrDesc = BlockList;
197 if (MemBase > MemEnd) {
198 return NULL;
199 }
200
201 Failed = TRUE;
202 }
203 //
204 // Now go through all the blocks and make sure none are in the way
205 //
206 while ((CurrDesc->Length != 0) && (!Failed)) {
207 if (IsOverlapped (MemBase, DataSize, (UINT8 *) (UINTN) CurrDesc->Union.DataBlock, (UINTN) CurrDesc->Length)) {
208 //
209 // Set our new base to the end of this block and start all over
210 //
211 Failed = TRUE;
212 MemBase = (UINT8 *) ((UINTN) CurrDesc->Union.DataBlock) + CurrDesc->Length;
213 CurrDesc = BlockList;
214 if (MemBase > MemEnd) {
215 return NULL;
216 }
217 }
218 CurrDesc++;
219 }
220 //
221 // Normal continuation -- jump to next block descriptor list
222 //
223 if (!Failed) {
224 CurrDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) CurrDesc->Union.ContinuationPointer;
225 }
226 }
227 return MemBase;
228 }
229
230 /**
231 Validate capsule by MemoryResource.
232
233 @param MemoryResource Pointer to the buffer of memory resource descriptor.
234 @param Address Address to be validated.
235 @param Size Size to be validated.
236
237 @retval TRUE No memory resource descriptor reported in HOB list before capsule Coalesce,
238 or it is valid in one MemoryResource.
239 FALSE It is not in any MemoryResource.
240
241 **/
242 BOOLEAN
243 ValidateCapsuleByMemoryResource (
244 IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
245 IN EFI_PHYSICAL_ADDRESS Address,
246 IN UINT64 Size
247 )
248 {
249 UINTN Index;
250
251 //
252 // Sanity Check
253 //
254 if (Size > MAX_ADDRESS) {
255 DEBUG ((DEBUG_ERROR, "ERROR: Size(0x%lx) > MAX_ADDRESS\n", Size));
256 return FALSE;
257 }
258
259 //
260 // Sanity Check
261 //
262 if (Address > (MAX_ADDRESS - Size)) {
263 DEBUG ((DEBUG_ERROR, "ERROR: Address(0x%lx) > (MAX_ADDRESS - Size(0x%lx))\n", Address, Size));
264 return FALSE;
265 }
266
267 if (MemoryResource == NULL) {
268 //
269 // No memory resource descriptor reported in HOB list before capsule Coalesce.
270 //
271 return TRUE;
272 }
273
274 for (Index = 0; MemoryResource[Index].ResourceLength != 0; Index++) {
275 if ((Address >= MemoryResource[Index].PhysicalStart) &&
276 ((Address + Size) <= (MemoryResource[Index].PhysicalStart + MemoryResource[Index].ResourceLength))) {
277 DEBUG ((DEBUG_INFO, "Address(0x%lx) Size(0x%lx) in MemoryResource[0x%x] - Start(0x%lx) Length(0x%lx)\n",
278 Address, Size,
279 Index, MemoryResource[Index].PhysicalStart, MemoryResource[Index].ResourceLength));
280 return TRUE;
281 }
282 }
283
284 DEBUG ((DEBUG_ERROR, "ERROR: Address(0x%lx) Size(0x%lx) not in any MemoryResource\n", Address, Size));
285 return FALSE;
286 }
287
288 /**
289 Check the integrity of the capsule descriptors.
290
291 @param BlockList Pointer to the capsule descriptors
292 @param MemoryResource Pointer to the buffer of memory resource descriptor.
293
294 @retval NULL BlockList is not valid.
295 @retval LastBlockDesc Last one Block in BlockList
296
297 **/
298 EFI_CAPSULE_BLOCK_DESCRIPTOR *
299 ValidateCapsuleIntegrity (
300 IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
301 IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource
302 )
303 {
304 EFI_CAPSULE_HEADER *CapsuleHeader;
305 UINT64 CapsuleSize;
306 UINTN CapsuleCount;
307 EFI_CAPSULE_BLOCK_DESCRIPTOR *Ptr;
308
309 DEBUG ((DEBUG_INFO, "ValidateCapsuleIntegrity\n"));
310
311 //
312 // Go through the list to look for inconsistencies. Check for:
313 // * misaligned block descriptors.
314 // * The first capsule header guid
315 // * The first capsule header flag
316 // * The first capsule header HeaderSize
317 // * Below check will be done in ValidateCapsuleByMemoryResource()
318 // Length > MAX_ADDRESS
319 // Ptr + sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR) > MAX_ADDRESS
320 // DataBlock + Length > MAX_ADDRESS
321 //
322 CapsuleSize = 0;
323 CapsuleCount = 0;
324 Ptr = BlockList;
325
326 if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
327 return NULL;
328 }
329
330 DEBUG ((DEBUG_INFO, "Ptr - 0x%x\n", Ptr));
331 DEBUG ((DEBUG_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
332 DEBUG ((DEBUG_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
333 while ((Ptr->Length != 0) || (Ptr->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
334 //
335 // Make sure the descriptor is aligned at UINT64 in memory
336 //
337 if ((UINTN) Ptr & (sizeof(UINT64) - 1)) {
338 DEBUG ((DEBUG_ERROR, "ERROR: BlockList address failed alignment check\n"));
339 return NULL;
340 }
341
342 if (Ptr->Length == 0) {
343 //
344 // Descriptor points to another list of block descriptors somewhere
345 // else.
346 //
347 Ptr = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Ptr->Union.ContinuationPointer;
348 if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
349 return NULL;
350 }
351 DEBUG ((DEBUG_INFO, "Ptr(C) - 0x%x\n", Ptr));
352 DEBUG ((DEBUG_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
353 DEBUG ((DEBUG_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
354 } else {
355 if (!ValidateCapsuleByMemoryResource (MemoryResource, Ptr->Union.DataBlock, Ptr->Length)) {
356 return NULL;
357 }
358
359 //
360 //To enhance the reliability of check-up, the first capsule's header is checked here.
361 //More reliabilities check-up will do later.
362 //
363 if (CapsuleSize == 0) {
364 //
365 //Move to the first capsule to check its header.
366 //
367 CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Ptr->Union.DataBlock);
368 //
369 // Sanity check
370 //
371 if (Ptr->Length < sizeof(EFI_CAPSULE_HEADER)) {
372 DEBUG ((DEBUG_ERROR, "ERROR: Ptr->Length(0x%lx) < sizeof(EFI_CAPSULE_HEADER)\n", Ptr->Length));
373 return NULL;
374 }
375 //
376 // Make sure HeaderSize field is valid
377 //
378 if (CapsuleHeader->HeaderSize > CapsuleHeader->CapsuleImageSize) {
379 DEBUG ((DEBUG_ERROR, "ERROR: CapsuleHeader->HeaderSize(0x%x) > CapsuleHeader->CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));
380 return NULL;
381 }
382 if (IsCapsuleCorrupted (CapsuleHeader)) {
383 return NULL;
384 }
385 CapsuleCount ++;
386 CapsuleSize = CapsuleHeader->CapsuleImageSize;
387 }
388
389 if (CapsuleSize >= Ptr->Length) {
390 CapsuleSize = CapsuleSize - Ptr->Length;
391 } else {
392 DEBUG ((DEBUG_ERROR, "ERROR: CapsuleSize(0x%lx) < Ptr->Length(0x%lx)\n", CapsuleSize, Ptr->Length));
393 //
394 // Sanity check
395 //
396 return NULL;
397 }
398
399 //
400 // Move to next BLOCK descriptor
401 //
402 Ptr++;
403 if (!ValidateCapsuleByMemoryResource (MemoryResource, (EFI_PHYSICAL_ADDRESS) (UINTN) Ptr, sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
404 return NULL;
405 }
406 DEBUG ((DEBUG_INFO, "Ptr(B) - 0x%x\n", Ptr));
407 DEBUG ((DEBUG_INFO, "Ptr->Length - 0x%x\n", Ptr->Length));
408 DEBUG ((DEBUG_INFO, "Ptr->Union - 0x%x\n", Ptr->Union.ContinuationPointer));
409 }
410 }
411
412 if (CapsuleCount == 0) {
413 //
414 // No any capsule is found in BlockList
415 //
416 DEBUG ((DEBUG_ERROR, "ERROR: CapsuleCount(0x%x) == 0\n", CapsuleCount));
417 return NULL;
418 }
419
420 if (CapsuleSize != 0) {
421 //
422 // Capsule data is incomplete.
423 //
424 DEBUG ((DEBUG_ERROR, "ERROR: CapsuleSize(0x%lx) != 0\n", CapsuleSize));
425 return NULL;
426 }
427
428 return Ptr;
429 }
430
431 /**
432 The capsule block descriptors may be fragmented and spread all over memory.
433 To simplify the coalescing of capsule blocks, first coalesce all the
434 capsule block descriptors low in memory.
435
436 The descriptors passed in can be fragmented throughout memory. Here
437 they are relocated into memory to turn them into a contiguous (null
438 terminated) array.
439
440 @param PeiServices pointer to PEI services table
441 @param BlockList pointer to the capsule block descriptors
442 @param NumDescriptors number of capsule data block descriptors, whose Length is non-zero.
443 @param MemBase base of system memory in which we can work
444 @param MemSize size of the system memory pointed to by MemBase
445
446 @retval NULL could not relocate the descriptors
447 @retval Pointer to the base of the successfully-relocated block descriptors.
448
449 **/
450 EFI_CAPSULE_BLOCK_DESCRIPTOR *
451 RelocateBlockDescriptors (
452 IN EFI_PEI_SERVICES **PeiServices,
453 IN EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList,
454 IN UINTN NumDescriptors,
455 IN UINT8 *MemBase,
456 IN UINTN MemSize
457 )
458 {
459 EFI_CAPSULE_BLOCK_DESCRIPTOR *NewBlockList;
460 EFI_CAPSULE_BLOCK_DESCRIPTOR *CurrBlockDescHead;
461 EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockDesc;
462 EFI_CAPSULE_BLOCK_DESCRIPTOR *PrevBlockDescTail;
463 UINTN BufferSize;
464 UINT8 *RelocBuffer;
465 UINTN BlockListSize;
466
467 //
468 // Get the info on the blocks and descriptors. Since we're going to move
469 // the descriptors low in memory, adjust the base/size values accordingly here.
470 // NumDescriptors is the number of legit data descriptors, so add one for
471 // a terminator. (Already done by caller, no check is needed.)
472 //
473
474 BufferSize = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
475 NewBlockList = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) MemBase;
476 if (MemSize < BufferSize) {
477 return NULL;
478 }
479
480 MemSize -= BufferSize;
481 MemBase += BufferSize;
482 //
483 // Go through all the blocks and make sure none are in the way
484 //
485 TempBlockDesc = BlockList;
486 while (TempBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
487 if (TempBlockDesc->Length == 0) {
488 //
489 // Next block of descriptors
490 //
491 TempBlockDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
492 } else {
493 //
494 // If the capsule data pointed to by this descriptor is in the way,
495 // move it.
496 //
497 if (IsOverlapped (
498 (UINT8 *) NewBlockList,
499 BufferSize,
500 (UINT8 *) (UINTN) TempBlockDesc->Union.DataBlock,
501 (UINTN) TempBlockDesc->Length
502 )) {
503 //
504 // Relocate the block
505 //
506 RelocBuffer = FindFreeMem (BlockList, MemBase, MemSize, (UINTN) TempBlockDesc->Length);
507 if (RelocBuffer == NULL) {
508 return NULL;
509 }
510
511 CopyMem ((VOID *) RelocBuffer, (VOID *) (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) TempBlockDesc->Length);
512 DEBUG ((DEBUG_INFO, "Capsule relocate descriptors from/to/size 0x%lX 0x%lX 0x%lX\n", TempBlockDesc->Union.DataBlock, (UINT64)(UINTN)RelocBuffer, TempBlockDesc->Length));
513 TempBlockDesc->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocBuffer;
514 }
515 TempBlockDesc++;
516 }
517 }
518 //
519 // Now go through all the block descriptors to make sure that they're not
520 // in the memory region we want to copy them to.
521 //
522 CurrBlockDescHead = BlockList;
523 PrevBlockDescTail = NULL;
524 while ((CurrBlockDescHead != NULL) && (CurrBlockDescHead->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
525 //
526 // Get the size of this list then see if it overlaps our low region
527 //
528 TempBlockDesc = CurrBlockDescHead;
529 BlockListSize = sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
530 while (TempBlockDesc->Length != 0) {
531 BlockListSize += sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
532 TempBlockDesc++;
533 }
534
535 if (IsOverlapped (
536 (UINT8 *) NewBlockList,
537 BufferSize,
538 (UINT8 *) CurrBlockDescHead,
539 BlockListSize
540 )) {
541 //
542 // Overlaps, so move it out of the way
543 //
544 RelocBuffer = FindFreeMem (BlockList, MemBase, MemSize, BlockListSize);
545 if (RelocBuffer == NULL) {
546 return NULL;
547 }
548 CopyMem ((VOID *) RelocBuffer, (VOID *) CurrBlockDescHead, BlockListSize);
549 DEBUG ((DEBUG_INFO, "Capsule reloc descriptor block #2\n"));
550 //
551 // Point the previous block's next point to this copied version. If
552 // the tail pointer is null, then this is the first descriptor block.
553 //
554 if (PrevBlockDescTail == NULL) {
555 BlockList = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) RelocBuffer;
556 } else {
557 PrevBlockDescTail->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocBuffer;
558 }
559 }
560 //
561 // Save our new tail and jump to the next block list
562 //
563 PrevBlockDescTail = TempBlockDesc;
564 CurrBlockDescHead = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
565 }
566 //
567 // Cleared out low memory. Now copy the descriptors down there.
568 //
569 TempBlockDesc = BlockList;
570 CurrBlockDescHead = NewBlockList;
571 while ((TempBlockDesc != NULL) && (TempBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
572 if (TempBlockDesc->Length != 0) {
573 CurrBlockDescHead->Union.DataBlock = TempBlockDesc->Union.DataBlock;
574 CurrBlockDescHead->Length = TempBlockDesc->Length;
575 CurrBlockDescHead++;
576 TempBlockDesc++;
577 } else {
578 TempBlockDesc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) TempBlockDesc->Union.ContinuationPointer;
579 }
580 }
581 //
582 // Null terminate
583 //
584 CurrBlockDescHead->Union.ContinuationPointer = (EFI_PHYSICAL_ADDRESS) (UINTN) NULL;
585 CurrBlockDescHead->Length = 0;
586 return NewBlockList;
587 }
588
589 /**
590 Determine if two buffers overlap in memory.
591
592 @param Buff1 pointer to first buffer
593 @param Size1 size of Buff1
594 @param Buff2 pointer to second buffer
595 @param Size2 size of Buff2
596
597 @retval TRUE Buffers overlap in memory.
598 @retval FALSE Buffer doesn't overlap.
599
600 **/
601 BOOLEAN
602 IsOverlapped (
603 UINT8 *Buff1,
604 UINTN Size1,
605 UINT8 *Buff2,
606 UINTN Size2
607 )
608 {
609 //
610 // If buff1's end is less than the start of buff2, then it's ok.
611 // Also, if buff1's start is beyond buff2's end, then it's ok.
612 //
613 if (((Buff1 + Size1) <= Buff2) || (Buff1 >= (Buff2 + Size2))) {
614 return FALSE;
615 }
616
617 return TRUE;
618 }
619
620 /**
621 Given a pointer to a capsule block descriptor, traverse the list to figure
622 out how many legitimate descriptors there are, and how big the capsule it
623 refers to is.
624
625 @param Desc Pointer to the capsule block descriptors
626 @param NumDescriptors Optional pointer to where to return the number of capsule data descriptors, whose Length is non-zero.
627 @param CapsuleSize Optional pointer to where to return the capsule image size
628 @param CapsuleNumber Optional pointer to where to return the number of capsule
629
630 @retval EFI_NOT_FOUND No descriptors containing data in the list
631 @retval EFI_SUCCESS Return data is valid
632
633 **/
634 EFI_STATUS
635 GetCapsuleInfo (
636 IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc,
637 IN OUT UINTN *NumDescriptors OPTIONAL,
638 IN OUT UINTN *CapsuleSize OPTIONAL,
639 IN OUT UINTN *CapsuleNumber OPTIONAL
640 )
641 {
642 UINTN Count;
643 UINTN Size;
644 UINTN Number;
645 UINTN ThisCapsuleImageSize;
646 EFI_CAPSULE_HEADER *CapsuleHeader;
647
648 DEBUG ((DEBUG_INFO, "GetCapsuleInfo enter\n"));
649
650 ASSERT (Desc != NULL);
651
652 Count = 0;
653 Size = 0;
654 Number = 0;
655 ThisCapsuleImageSize = 0;
656
657 while (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
658 if (Desc->Length == 0) {
659 //
660 // Descriptor points to another list of block descriptors somewhere
661 //
662 Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Desc->Union.ContinuationPointer;
663 } else {
664 //
665 // Sanity Check
666 // It is needed, because ValidateCapsuleIntegrity() only validate one individual capsule Size.
667 // While here we need check all capsules size.
668 //
669 if (Desc->Length >= (MAX_ADDRESS - Size)) {
670 DEBUG ((DEBUG_ERROR, "ERROR: Desc->Length(0x%lx) >= (MAX_ADDRESS - Size(0x%x))\n", Desc->Length, Size));
671 return EFI_OUT_OF_RESOURCES;
672 }
673 Size += (UINTN) Desc->Length;
674 Count++;
675
676 //
677 // See if this is first capsule's header
678 //
679 if (ThisCapsuleImageSize == 0) {
680 CapsuleHeader = (EFI_CAPSULE_HEADER*)((UINTN)Desc->Union.DataBlock);
681 //
682 // This has been checked in ValidateCapsuleIntegrity()
683 //
684 Number ++;
685 ThisCapsuleImageSize = CapsuleHeader->CapsuleImageSize;
686 }
687
688 //
689 // This has been checked in ValidateCapsuleIntegrity()
690 //
691 ASSERT (ThisCapsuleImageSize >= Desc->Length);
692 ThisCapsuleImageSize = (UINTN)(ThisCapsuleImageSize - Desc->Length);
693
694 //
695 // Move to next
696 //
697 Desc++;
698 }
699 }
700 //
701 // If no descriptors, then fail
702 //
703 if (Count == 0) {
704 DEBUG ((DEBUG_ERROR, "ERROR: Count == 0\n"));
705 return EFI_NOT_FOUND;
706 }
707
708 //
709 // checked in ValidateCapsuleIntegrity()
710 //
711 ASSERT (ThisCapsuleImageSize == 0);
712
713 if (NumDescriptors != NULL) {
714 *NumDescriptors = Count;
715 }
716
717 if (CapsuleSize != NULL) {
718 *CapsuleSize = Size;
719 }
720
721 if (CapsuleNumber != NULL) {
722 *CapsuleNumber = Number;
723 }
724
725 return EFI_SUCCESS;
726 }
727
728 /**
729 Check every capsule header.
730
731 @param CapsuleHeader The pointer to EFI_CAPSULE_HEADER
732
733 @retval FALSE Capsule is OK
734 @retval TRUE Capsule is corrupted
735
736 **/
737 BOOLEAN
738 IsCapsuleCorrupted (
739 IN EFI_CAPSULE_HEADER *CapsuleHeader
740 )
741 {
742 //
743 //A capsule to be updated across a system reset should contain CAPSULE_FLAGS_PERSIST_ACROSS_RESET.
744 //
745 if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
746 return TRUE;
747 }
748 //
749 //Make sure the flags combination is supported by the platform.
750 //
751 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
752 return TRUE;
753 }
754 if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
755 return TRUE;
756 }
757
758 return FALSE;
759 }
760
761 /**
762 Try to verify the integrity of a capsule test pattern before the
763 capsule gets coalesced. This can be useful in narrowing down
764 where capsule data corruption occurs.
765
766 The test pattern mode fills in memory with a counting UINT32 value.
767 If the capsule is not divided up in a multiple of 4-byte blocks, then
768 things get messy doing the check. Therefore there are some cases
769 here where we just give up and skip the pre-coalesce check.
770
771 @param PeiServices PEI services table
772 @param Desc Pointer to capsule descriptors
773 **/
774 VOID
775 CapsuleTestPatternPreCoalesce (
776 IN EFI_PEI_SERVICES **PeiServices,
777 IN EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc
778 )
779 {
780 UINT32 *TestPtr;
781 UINT32 TestCounter;
782 UINT32 TestSize;
783
784 DEBUG ((DEBUG_INFO, "CapsuleTestPatternPreCoalesce\n"));
785
786 //
787 // Find first data descriptor
788 //
789 while ((Desc->Length == 0) && (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
790 Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Desc->Union.ContinuationPointer;
791 }
792
793 if (Desc->Union.ContinuationPointer == 0) {
794 return ;
795 }
796 //
797 // First one better be long enough to at least hold the test signature
798 //
799 if (Desc->Length < sizeof (UINT32)) {
800 DEBUG ((DEBUG_INFO, "Capsule test pattern pre-coalesce punted #1\n"));
801 return ;
802 }
803
804 TestPtr = (UINT32 *) (UINTN) Desc->Union.DataBlock;
805 //
806 // 0x54534554 "TEST"
807 //
808 if (*TestPtr != 0x54534554) {
809 return ;
810 }
811
812 TestCounter = 0;
813 TestSize = (UINT32) Desc->Length - 2 * sizeof (UINT32);
814 //
815 // Skip over the signature and the size fields in the pattern data header
816 //
817 TestPtr += 2;
818 while (1) {
819 if ((TestSize & 0x03) != 0) {
820 DEBUG ((DEBUG_INFO, "Capsule test pattern pre-coalesce punted #2\n"));
821 return ;
822 }
823
824 while (TestSize > 0) {
825 if (*TestPtr != TestCounter) {
826 DEBUG ((DEBUG_INFO, "Capsule test pattern pre-coalesce failed data corruption check\n"));
827 return ;
828 }
829
830 TestSize -= sizeof (UINT32);
831 TestCounter++;
832 TestPtr++;
833 }
834 Desc++;
835 while ((Desc->Length == 0) && (Desc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
836 Desc = (EFI_CAPSULE_BLOCK_DESCRIPTOR *) (UINTN) Desc->Union.ContinuationPointer;
837 }
838
839 if (Desc->Union.ContinuationPointer == (EFI_PHYSICAL_ADDRESS) (UINTN) NULL) {
840 return ;
841 }
842 TestSize = (UINT32) Desc->Length;
843 TestPtr = (UINT32 *) (UINTN) Desc->Union.DataBlock;
844 }
845 }
846
847 /**
848 Checks for the presence of capsule descriptors.
849 Get capsule descriptors from variable CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
850
851 @param BlockListBuffer Pointer to the buffer of capsule descriptors variables
852 @param MemoryResource Pointer to the buffer of memory resource descriptor.
853 @param BlockDescriptorList Pointer to the capsule descriptors list
854
855 @retval EFI_SUCCESS a valid capsule is present
856 @retval EFI_NOT_FOUND if a valid capsule is not present
857 **/
858 EFI_STATUS
859 BuildCapsuleDescriptors (
860 IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
861 IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
862 OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptorList
863 )
864 {
865 UINTN Index;
866 EFI_CAPSULE_BLOCK_DESCRIPTOR *LastBlock;
867 EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlock;
868 EFI_CAPSULE_BLOCK_DESCRIPTOR *HeadBlock;
869
870 DEBUG ((DEBUG_INFO, "BuildCapsuleDescriptors enter\n"));
871
872 LastBlock = NULL;
873 HeadBlock = NULL;
874 TempBlock = NULL;
875 Index = 0;
876
877 while (BlockListBuffer[Index] != 0) {
878 //
879 // Test integrity of descriptors.
880 //
881 if (BlockListBuffer[Index] < MAX_ADDRESS) {
882 TempBlock = ValidateCapsuleIntegrity ((EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index], MemoryResource);
883 if (TempBlock != NULL) {
884 if (LastBlock == NULL) {
885 LastBlock = TempBlock;
886
887 //
888 // Return the base of the block descriptors
889 //
890 HeadBlock = (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)BlockListBuffer[Index];
891 } else {
892 //
893 // Combine the different BlockList into single BlockList.
894 //
895 LastBlock->Union.DataBlock = (EFI_PHYSICAL_ADDRESS)(UINTN)BlockListBuffer[Index];
896 LastBlock->Length = 0;
897 LastBlock = TempBlock;
898 }
899 }
900 } else {
901 DEBUG ((DEBUG_ERROR, "ERROR: BlockListBuffer[Index](0x%lx) < MAX_ADDRESS\n", BlockListBuffer[Index]));
902 }
903 Index ++;
904 }
905
906 if (HeadBlock != NULL) {
907 *BlockDescriptorList = HeadBlock;
908 return EFI_SUCCESS;
909 }
910 return EFI_NOT_FOUND;
911 }
912
913 /**
914 The function to coalesce a fragmented capsule in memory.
915
916 Memory Map for coalesced capsule:
917 MemBase + ---->+---------------------------+<-----------+
918 MemSize | ------------------------- | |
919 | | Capsule [Num-1] | | |
920 | ------------------------- | |
921 | | ................ | | |
922 | ------------------------- | |
923 | | Capsule [1] | | |
924 | ------------------------- | |
925 | | Capsule [0] | | |
926 | ------------------------- | |
927 | Capsule Image | |
928 CapsuleImageBase-->+---------------------------+
929 | ------------------------- | |
930 | | CapsuleOffset[Num-1] | | |
931 | ------------------------- | |
932 | | ................ | | CapsuleSize
933 | ------------------------- | |
934 | | CapsuleOffset[1] | | |
935 | ------------------------- | |
936 | | CapsuleOffset[0] | | |
937 |---------------------------| |
938 | | CapsuleNumber | | |
939 | ------------------------- | |
940 | | CapsuleAllImageSize | | |
941 | ------------------------- | |
942 | PrivateData | |
943 DestPtr ---->+---------------------------+<-----------+
944 | | |
945 | FreeMem | FreeMemSize
946 | | |
947 FreeMemBase --->+---------------------------+<-----------+
948 | Terminator |
949 +---------------------------+
950 | BlockDescriptor n |
951 +---------------------------+
952 | ................. |
953 +---------------------------+
954 | BlockDescriptor 1 |
955 +---------------------------+
956 | BlockDescriptor 0 |
957 +---------------------------+
958 | PrivateDataDesc 0 |
959 MemBase ---->+---------------------------+<----- BlockList
960
961 Caution: This function may receive untrusted input.
962 The capsule data is external input, so this routine will do basic validation before
963 coalesce capsule data into memory.
964
965 @param PeiServices General purpose services available to every PEIM.
966 @param BlockListBuffer Pointer to the buffer of Capsule Descriptor Variables.
967 @param MemoryResource Pointer to the buffer of memory resource descriptor.
968 @param MemoryBase Pointer to the base of a block of memory that we can walk
969 all over while trying to coalesce our buffers.
970 On output, this variable will hold the base address of
971 a coalesced capsule.
972 @param MemorySize Size of the memory region pointed to by MemoryBase.
973 On output, this variable will contain the size of the
974 coalesced capsule.
975
976 @retval EFI_NOT_FOUND If we could not find the capsule descriptors.
977
978 @retval EFI_BUFFER_TOO_SMALL
979 If we could not coalesce the capsule in the memory
980 region provided to us.
981
982 @retval EFI_SUCCESS Processed the capsule successfully.
983 **/
984 EFI_STATUS
985 EFIAPI
986 CapsuleDataCoalesce (
987 IN EFI_PEI_SERVICES **PeiServices,
988 IN EFI_PHYSICAL_ADDRESS *BlockListBuffer,
989 IN MEMORY_RESOURCE_DESCRIPTOR *MemoryResource,
990 IN OUT VOID **MemoryBase,
991 IN OUT UINTN *MemorySize
992 )
993 {
994 VOID *NewCapsuleBase;
995 VOID *CapsuleImageBase;
996 UINTN CapsuleIndex;
997 UINT8 *FreeMemBase;
998 UINT8 *DestPtr;
999 UINTN DestLength;
1000 UINT8 *RelocPtr;
1001 UINTN CapsuleTimes;
1002 UINT64 SizeLeft;
1003 UINT64 CapsuleImageSize;
1004 UINTN CapsuleSize;
1005 UINTN CapsuleNumber;
1006 UINTN DescriptorsSize;
1007 UINTN FreeMemSize;
1008 UINTN NumDescriptors;
1009 BOOLEAN CapsuleBeginFlag;
1010 EFI_STATUS Status;
1011 EFI_CAPSULE_HEADER *CapsuleHeader;
1012 EFI_CAPSULE_PEIM_PRIVATE_DATA PrivateData;
1013 EFI_CAPSULE_PEIM_PRIVATE_DATA *PrivateDataPtr;
1014 EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockList;
1015 EFI_CAPSULE_BLOCK_DESCRIPTOR *CurrentBlockDesc;
1016 EFI_CAPSULE_BLOCK_DESCRIPTOR *TempBlockDesc;
1017 EFI_CAPSULE_BLOCK_DESCRIPTOR PrivateDataDesc[2];
1018
1019 DEBUG ((DEBUG_INFO, "CapsuleDataCoalesce enter\n"));
1020
1021 CapsuleIndex = 0;
1022 SizeLeft = 0;
1023 CapsuleTimes = 0;
1024 CapsuleImageSize = 0;
1025 PrivateDataPtr = NULL;
1026 CapsuleHeader = NULL;
1027 CapsuleBeginFlag = TRUE;
1028 CapsuleSize = 0;
1029 NumDescriptors = 0;
1030
1031 //
1032 // Build capsule descriptors list
1033 //
1034 Status = BuildCapsuleDescriptors (BlockListBuffer, MemoryResource, &BlockList);
1035 if (EFI_ERROR (Status)) {
1036 return Status;
1037 }
1038
1039 DEBUG_CODE (
1040 CapsuleTestPatternPreCoalesce (PeiServices, BlockList);
1041 );
1042
1043 //
1044 // Get the size of our descriptors and the capsule size. GetCapsuleInfo()
1045 // returns the number of descriptors that actually point to data, so add
1046 // one for a terminator. Do that below.
1047 //
1048 Status = GetCapsuleInfo (BlockList, &NumDescriptors, &CapsuleSize, &CapsuleNumber);
1049 if (EFI_ERROR (Status)) {
1050 return Status;
1051 }
1052 DEBUG ((DEBUG_INFO, "CapsuleSize - 0x%x\n", CapsuleSize));
1053 DEBUG ((DEBUG_INFO, "CapsuleNumber - 0x%x\n", CapsuleNumber));
1054 DEBUG ((DEBUG_INFO, "NumDescriptors - 0x%x\n", NumDescriptors));
1055 if ((CapsuleSize == 0) || (NumDescriptors == 0) || (CapsuleNumber == 0)) {
1056 return EFI_NOT_FOUND;
1057 }
1058
1059 if (CapsuleNumber - 1 >= (MAX_ADDRESS - (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + sizeof(UINT64))) / sizeof(UINT64)) {
1060 DEBUG ((DEBUG_ERROR, "ERROR: CapsuleNumber - 0x%x\n", CapsuleNumber));
1061 return EFI_BUFFER_TOO_SMALL;
1062 }
1063
1064 //
1065 // Initialize our local copy of private data. When we're done, we'll create a
1066 // descriptor for it as well so that it can be put into free memory without
1067 // trashing anything.
1068 //
1069 PrivateData.Signature = EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE;
1070 PrivateData.CapsuleAllImageSize = (UINT64) CapsuleSize;
1071 PrivateData.CapsuleNumber = (UINT64) CapsuleNumber;
1072 PrivateData.CapsuleOffset[0] = 0;
1073 //
1074 // NOTE: Only data in sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) is valid, CapsuleOffset field is uninitialized at this moment.
1075 // The code sets partial length here for Descriptor.Length check, but later it will use full length to reserve those PrivateData region.
1076 //
1077 PrivateDataDesc[0].Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) &PrivateData;
1078 PrivateDataDesc[0].Length = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA);
1079 PrivateDataDesc[1].Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) BlockList;
1080 PrivateDataDesc[1].Length = 0;
1081 //
1082 // Add PrivateDataDesc[0] in beginning, as it is new descriptor. PrivateDataDesc[1] is NOT needed.
1083 // In addition, one NULL terminator is added in the end. See RelocateBlockDescriptors().
1084 //
1085 NumDescriptors += 2;
1086 //
1087 // Sanity check
1088 //
1089 if (CapsuleSize >= (MAX_ADDRESS - (sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64) + sizeof(UINT64)))) {
1090 DEBUG ((DEBUG_ERROR, "ERROR: CapsuleSize - 0x%x\n", CapsuleSize));
1091 return EFI_BUFFER_TOO_SMALL;
1092 }
1093 //
1094 // Need add sizeof(UINT64) for PrivateData alignment
1095 //
1096 CapsuleSize += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64) + sizeof(UINT64);
1097 BlockList = PrivateDataDesc;
1098 //
1099 // Sanity check
1100 //
1101 if (NumDescriptors >= (MAX_ADDRESS / sizeof(EFI_CAPSULE_BLOCK_DESCRIPTOR))) {
1102 DEBUG ((DEBUG_ERROR, "ERROR: NumDescriptors - 0x%x\n", NumDescriptors));
1103 return EFI_BUFFER_TOO_SMALL;
1104 }
1105 DescriptorsSize = NumDescriptors * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
1106 //
1107 // Sanity check
1108 //
1109 if (DescriptorsSize >= (MAX_ADDRESS - CapsuleSize)) {
1110 DEBUG ((DEBUG_ERROR, "ERROR: DescriptorsSize - 0x%lx, CapsuleSize - 0x%lx\n", (UINT64)DescriptorsSize, (UINT64)CapsuleSize));
1111 return EFI_BUFFER_TOO_SMALL;
1112 }
1113
1114 //
1115 // Don't go below some min address. If the base is below it,
1116 // then move it up and adjust the size accordingly.
1117 //
1118 DEBUG ((DEBUG_INFO, "Capsule Memory range from 0x%8X to 0x%8X\n", (UINTN) *MemoryBase, (UINTN)*MemoryBase + *MemorySize));
1119 if ((UINTN)*MemoryBase < (UINTN) MIN_COALESCE_ADDR) {
1120 if (((UINTN)*MemoryBase + *MemorySize) < (UINTN) MIN_COALESCE_ADDR) {
1121 DEBUG ((DEBUG_ERROR, "ERROR: *MemoryBase + *MemorySize - 0x%x\n", (UINTN)*MemoryBase + *MemorySize));
1122 return EFI_BUFFER_TOO_SMALL;
1123 } else {
1124 *MemorySize = *MemorySize - ((UINTN) MIN_COALESCE_ADDR - (UINTN) *MemoryBase);
1125 *MemoryBase = (VOID *) (UINTN) MIN_COALESCE_ADDR;
1126 }
1127 }
1128
1129 if (*MemorySize <= (CapsuleSize + DescriptorsSize)) {
1130 DEBUG ((DEBUG_ERROR, "ERROR: CapsuleSize + DescriptorsSize - 0x%x\n", CapsuleSize + DescriptorsSize));
1131 return EFI_BUFFER_TOO_SMALL;
1132 }
1133
1134 FreeMemBase = *MemoryBase;
1135 FreeMemSize = *MemorySize;
1136 DEBUG ((DEBUG_INFO, "Capsule Free Memory from 0x%8X to 0x%8X\n", (UINTN) FreeMemBase, (UINTN) FreeMemBase + FreeMemSize));
1137
1138 //
1139 // Relocate all the block descriptors to low memory to make further
1140 // processing easier.
1141 //
1142 BlockList = RelocateBlockDescriptors (PeiServices, BlockList, NumDescriptors, FreeMemBase, FreeMemSize);
1143 if (BlockList == NULL) {
1144 //
1145 // Not enough room to relocate the descriptors
1146 //
1147 return EFI_BUFFER_TOO_SMALL;
1148 }
1149
1150 //
1151 // Take the top of memory for the capsule. UINT64 align up.
1152 //
1153 DestPtr = FreeMemBase + FreeMemSize - CapsuleSize;
1154 DestPtr = (UINT8 *) (((UINTN)DestPtr + sizeof (UINT64) - 1) & ~(sizeof (UINT64) - 1));
1155 FreeMemBase = (UINT8 *) BlockList + DescriptorsSize;
1156 FreeMemSize = (UINTN) DestPtr - (UINTN) FreeMemBase;
1157 NewCapsuleBase = (VOID *) DestPtr;
1158 CapsuleImageBase = (UINT8 *)NewCapsuleBase + sizeof(EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
1159
1160 PrivateDataPtr = (EFI_CAPSULE_PEIM_PRIVATE_DATA *) NewCapsuleBase;
1161
1162 //
1163 // Move all the blocks to the top (high) of memory.
1164 // Relocate all the obstructing blocks. Note that the block descriptors
1165 // were coalesced when they were relocated, so we can just ++ the pointer.
1166 //
1167 CurrentBlockDesc = BlockList;
1168 while ((CurrentBlockDesc->Length != 0) || (CurrentBlockDesc->Union.ContinuationPointer != (EFI_PHYSICAL_ADDRESS) (UINTN) NULL)) {
1169 if (CapsuleTimes == 0) {
1170 //
1171 // The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
1172 // CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
1173 //
1174 ASSERT (CurrentBlockDesc->Union.DataBlock == (UINT64)(UINTN)&PrivateData);
1175 DestLength = sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
1176 } else {
1177 DestLength = (UINTN)CurrentBlockDesc->Length;
1178 }
1179 //
1180 // See if any of the remaining capsule blocks are in the way
1181 //
1182 TempBlockDesc = CurrentBlockDesc;
1183 while (TempBlockDesc->Length != 0) {
1184 //
1185 // Is this block in the way of where we want to copy the current descriptor to?
1186 //
1187 if (IsOverlapped (
1188 (UINT8 *) DestPtr,
1189 (UINTN) DestLength,
1190 (UINT8 *) (UINTN) TempBlockDesc->Union.DataBlock,
1191 (UINTN) TempBlockDesc->Length
1192 )) {
1193 //
1194 // Relocate the block
1195 //
1196 RelocPtr = FindFreeMem (BlockList, FreeMemBase, FreeMemSize, (UINTN) TempBlockDesc->Length);
1197 if (RelocPtr == NULL) {
1198 return EFI_BUFFER_TOO_SMALL;
1199 }
1200
1201 CopyMem ((VOID *) RelocPtr, (VOID *) (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) TempBlockDesc->Length);
1202 DEBUG ((DEBUG_INFO, "Capsule reloc data block from 0x%8X to 0x%8X with size 0x%8X\n",
1203 (UINTN) TempBlockDesc->Union.DataBlock, (UINTN) RelocPtr, (UINTN) TempBlockDesc->Length));
1204
1205 TempBlockDesc->Union.DataBlock = (EFI_PHYSICAL_ADDRESS) (UINTN) RelocPtr;
1206 }
1207 //
1208 // Next descriptor
1209 //
1210 TempBlockDesc++;
1211 }
1212 //
1213 // Ok, we made it through. Copy the block.
1214 // we just support greping one capsule from the lists of block descs list.
1215 //
1216 CapsuleTimes ++;
1217 //
1218 //Skip the first block descriptor that filled with EFI_CAPSULE_PEIM_PRIVATE_DATA
1219 //
1220 if (CapsuleTimes > 1) {
1221 //
1222 //For every capsule entry point, check its header to determine whether to relocate it.
1223 //If it is invalid, skip it and move on to the next capsule. If it is valid, relocate it.
1224 //
1225 if (CapsuleBeginFlag) {
1226 CapsuleBeginFlag = FALSE;
1227 CapsuleHeader = (EFI_CAPSULE_HEADER*)(UINTN)CurrentBlockDesc->Union.DataBlock;
1228 SizeLeft = CapsuleHeader->CapsuleImageSize;
1229
1230 //
1231 // No more check here is needed, because IsCapsuleCorrupted() already in ValidateCapsuleIntegrity()
1232 //
1233 ASSERT (CapsuleIndex < CapsuleNumber);
1234
1235 //
1236 // Relocate this capsule
1237 //
1238 CapsuleImageSize += SizeLeft;
1239 //
1240 // Cache the begin offset of this capsule
1241 //
1242 ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
1243 ASSERT ((UINTN)DestPtr >= (UINTN)CapsuleImageBase);
1244 PrivateDataPtr->CapsuleOffset[CapsuleIndex++] = (UINTN)DestPtr - (UINTN)CapsuleImageBase;
1245 }
1246
1247 //
1248 // Below ASSERT is checked in ValidateCapsuleIntegrity()
1249 //
1250 ASSERT (CurrentBlockDesc->Length <= SizeLeft);
1251
1252 CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) (CurrentBlockDesc->Union.DataBlock), (UINTN)CurrentBlockDesc->Length);
1253 DEBUG ((DEBUG_INFO, "Capsule coalesce block no.0x%lX from 0x%lX to 0x%lX with size 0x%lX\n",(UINT64)CapsuleTimes,
1254 CurrentBlockDesc->Union.DataBlock, (UINT64)(UINTN)DestPtr, CurrentBlockDesc->Length));
1255 DestPtr += CurrentBlockDesc->Length;
1256 SizeLeft -= CurrentBlockDesc->Length;
1257
1258 if (SizeLeft == 0) {
1259 //
1260 //Here is the end of the current capsule image.
1261 //
1262 CapsuleBeginFlag = TRUE;
1263 }
1264 } else {
1265 //
1266 // The first entry is the block descriptor for EFI_CAPSULE_PEIM_PRIVATE_DATA.
1267 // CapsuleOffset field is uninitialized at this time. No need copy it, but need to reserve for future use.
1268 //
1269 ASSERT (CurrentBlockDesc->Length == sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA));
1270 ASSERT ((UINTN)DestPtr == (UINTN)NewCapsuleBase);
1271 CopyMem ((VOID *) DestPtr, (VOID *) (UINTN) CurrentBlockDesc->Union.DataBlock, (UINTN) CurrentBlockDesc->Length);
1272 DestPtr += sizeof (EFI_CAPSULE_PEIM_PRIVATE_DATA) + (CapsuleNumber - 1) * sizeof(UINT64);
1273 }
1274 //
1275 //Walk through the block descriptor list.
1276 //
1277 CurrentBlockDesc++;
1278 }
1279 //
1280 // We return the base of memory we want reserved, and the size.
1281 // The memory peim should handle it appropriately from there.
1282 //
1283 *MemorySize = (UINTN) CapsuleSize;
1284 *MemoryBase = (VOID *) NewCapsuleBase;
1285
1286 ASSERT (PrivateDataPtr->Signature == EFI_CAPSULE_PEIM_PRIVATE_DATA_SIGNATURE);
1287 ASSERT (PrivateDataPtr->CapsuleAllImageSize == CapsuleImageSize);
1288 ASSERT (PrivateDataPtr->CapsuleNumber == CapsuleIndex);
1289
1290 return EFI_SUCCESS;
1291 }