Import PCD dxe and PCD pei modules.
[mirror_edk2.git] / MdeModulePkg / Universal / PCD / Pei / Pcd.c
1 /** @file PCD PEIM
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 Module Name: Pcd.c
14
15 **/
16
17 //
18 // Include common header file for this module.
19 //
20 #include "CommonHeader.h"
21
22 #include "Service.h"
23
24
25 PCD_PPI mPcdPpiInstance = {
26 PeiPcdSetSku,
27
28 PeiPcdGet8,
29 PeiPcdGet16,
30 PeiPcdGet32,
31 PeiPcdGet64,
32 PeiPcdGetPtr,
33 PeiPcdGetBool,
34 PeiPcdGetSize,
35
36 PeiPcdGet8Ex,
37 PeiPcdGet16Ex,
38 PeiPcdGet32Ex,
39 PeiPcdGet64Ex,
40 PeiPcdGetPtrEx,
41 PeiPcdGetBoolEx,
42 PeiPcdGetSizeEx,
43
44 PeiPcdSet8,
45 PeiPcdSet16,
46 PeiPcdSet32,
47 PeiPcdSet64,
48 PeiPcdSetPtr,
49 PeiPcdSetBool,
50
51 PeiPcdSet8Ex,
52 PeiPcdSet16Ex,
53 PeiPcdSet32Ex,
54 PeiPcdSet64Ex,
55 PeiPcdSetPtrEx,
56 PeiPcdSetBoolEx,
57
58 PeiRegisterCallBackOnSet,
59 PcdUnRegisterCallBackOnSet,
60 PeiPcdGetNextToken,
61 PeiPcdGetNextTokenSpace
62 };
63
64
65
66 STATIC EFI_PEI_PPI_DESCRIPTOR mPpiPCD = {
67 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
68 &gPcdPpiGuid,
69 &mPcdPpiInstance
70 };
71
72
73
74 EFI_STATUS
75 EFIAPI
76 PcdPeimInit (
77 IN EFI_FFS_FILE_HEADER *FfsHeader,
78 IN EFI_PEI_SERVICES **PeiServices
79 )
80 {
81 EFI_STATUS Status;
82
83 BuildPcdDatabase ();
84
85 Status = PeiServicesInstallPpi (&mPpiPCD);
86
87 ASSERT_EFI_ERROR (Status);
88
89 return EFI_SUCCESS;
90 }
91
92 VOID
93 EFIAPI
94 PeiPcdSetSku (
95 IN UINTN SkuId
96 )
97 {
98
99 GetPcdDatabase()->Init.SystemSkuId = (SKU_ID) SkuId;
100
101 return;
102 }
103
104
105
106 UINT8
107 EFIAPI
108 PeiPcdGet8 (
109 IN UINTN TokenNumber
110 )
111 {
112 return *((UINT8 *) GetWorker (TokenNumber, sizeof (UINT8)));
113 }
114
115
116
117 UINT16
118 EFIAPI
119 PeiPcdGet16 (
120 IN UINTN TokenNumber
121 )
122 {
123 return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
124 }
125
126
127
128 UINT32
129 EFIAPI
130 PeiPcdGet32 (
131 IN UINTN TokenNumber
132 )
133 {
134 return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
135 }
136
137
138
139 UINT64
140 EFIAPI
141 PeiPcdGet64 (
142 IN UINTN TokenNumber
143 )
144 {
145 return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));
146 }
147
148
149
150 VOID *
151 EFIAPI
152 PeiPcdGetPtr (
153 IN UINTN TokenNumber
154 )
155 {
156 return GetWorker (TokenNumber, 0);
157 }
158
159
160
161 BOOLEAN
162 EFIAPI
163 PeiPcdGetBool (
164 IN UINTN TokenNumber
165 )
166 {
167 return *((BOOLEAN *) GetWorker (TokenNumber, sizeof (BOOLEAN)));
168 }
169
170
171
172 UINTN
173 EFIAPI
174 PeiPcdGetSize (
175 IN UINTN TokenNumber
176 )
177 {
178 PEI_PCD_DATABASE *PeiPcdDb;
179 UINTN Size;
180 UINTN MaxSize;
181
182 //
183 // If DebugAssertEnabled is TRUE, we still need to provide the GET size
184 // function as GetWorker and SetWoker need this function to do ASSERT.
185 //
186 if ((!FeaturePcdGet(PcdPeiPcdDatabaseGetSizeEnabled)) &&
187 (!DebugAssertEnabled ())) {
188 return 0;
189 }
190
191 PeiPcdDb = GetPcdDatabase ();
192 //
193 // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
194 // We have to decrement TokenNumber by 1 to make it usable
195 // as the array index.
196 //
197 TokenNumber--;
198
199 // EBC compiler is very choosy. It may report warning about comparison
200 // between UINTN and 0 . So we add 1 in each size of the
201 // comparison.
202 ASSERT (TokenNumber + 1 < PEI_LOCAL_TOKEN_NUMBER + 1);
203
204 Size = (PeiPcdDb->Init.LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
205
206 if (Size == 0) {
207 //
208 // For pointer type, we need to scan the SIZE_TABLE to get the current size.
209 //
210 return GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
211 } else {
212 return Size;
213 }
214
215 }
216
217
218
219 UINT8
220 EFIAPI
221 PeiPcdGet8Ex (
222 IN CONST EFI_GUID *Guid,
223 IN UINTN ExTokenNumber
224 )
225 {
226 return *((UINT8 *) ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));
227 }
228
229
230
231 UINT16
232 EFIAPI
233 PeiPcdGet16Ex (
234 IN CONST EFI_GUID *Guid,
235 IN UINTN ExTokenNumber
236 )
237 {
238 return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));
239 }
240
241
242
243 UINT32
244 EFIAPI
245 PeiPcdGet32Ex (
246 IN CONST EFI_GUID *Guid,
247 IN UINTN ExTokenNumber
248 )
249 {
250 return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));
251 }
252
253
254
255 UINT64
256 EFIAPI
257 PeiPcdGet64Ex (
258 IN CONST EFI_GUID *Guid,
259 IN UINTN ExTokenNumber
260 )
261 {
262 return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));
263 }
264
265
266
267 VOID *
268 EFIAPI
269 PeiPcdGetPtrEx (
270 IN CONST EFI_GUID *Guid,
271 IN UINTN ExTokenNumber
272 )
273 {
274 return ExGetWorker (Guid, ExTokenNumber, 0);
275 }
276
277
278
279 BOOLEAN
280 EFIAPI
281 PeiPcdGetBoolEx (
282 IN CONST EFI_GUID *Guid,
283 IN UINTN ExTokenNumber
284 )
285 {
286 return *((BOOLEAN *) ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));
287 }
288
289
290
291 UINTN
292 EFIAPI
293 PeiPcdGetSizeEx (
294 IN CONST EFI_GUID *Guid,
295 IN UINTN ExTokenNumber
296 )
297 {
298 if ((!FeaturePcdGet (PcdPeiPcdDatabaseGetSizeEnabled)) || !FeaturePcdGet (PcdPeiPcdDatabaseExEnabled)) {
299 return 0;
300 }
301
302 return PeiPcdGetSize (GetExPcdTokenNumber (Guid, ExTokenNumber));
303 }
304
305
306
307 EFI_STATUS
308 EFIAPI
309 PeiPcdSet8 (
310 IN UINTN TokenNumber,
311 IN UINT8 Value
312 )
313 {
314 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
315 }
316
317
318
319 EFI_STATUS
320 EFIAPI
321 PeiPcdSet16 (
322 IN UINTN TokenNumber,
323 IN UINT16 Value
324 )
325 {
326 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
327 }
328
329
330
331 EFI_STATUS
332 EFIAPI
333 PeiPcdSet32 (
334 IN UINTN TokenNumber,
335 IN UINT32 Value
336 )
337 {
338 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
339 }
340
341
342
343 EFI_STATUS
344 EFIAPI
345 PeiPcdSet64 (
346 IN UINTN TokenNumber,
347 IN UINT64 Value
348 )
349 {
350 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
351 }
352
353
354 EFI_STATUS
355 EFIAPI
356 PeiPcdSetPtr (
357 IN UINTN TokenNumber,
358 IN OUT UINTN *SizeOfBuffer,
359 IN VOID *Buffer
360 )
361 {
362 return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
363 }
364
365
366
367 EFI_STATUS
368 EFIAPI
369 PeiPcdSetBool (
370 IN UINTN TokenNumber,
371 IN BOOLEAN Value
372 )
373 {
374 return SetValueWorker (TokenNumber, &Value, sizeof (Value));
375 }
376
377
378
379 EFI_STATUS
380 EFIAPI
381 PeiPcdSet8Ex (
382 IN CONST EFI_GUID *Guid,
383 IN UINTN ExTokenNumber,
384 IN UINT8 Value
385 )
386 {
387 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
388 }
389
390
391
392 EFI_STATUS
393 EFIAPI
394 PeiPcdSet16Ex (
395 IN CONST EFI_GUID *Guid,
396 IN UINTN ExTokenNumber,
397 IN UINT16 Value
398 )
399 {
400 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
401 }
402
403
404
405 EFI_STATUS
406 EFIAPI
407 PeiPcdSet32Ex (
408 IN CONST EFI_GUID *Guid,
409 IN UINTN ExTokenNumber,
410 IN UINT32 Value
411 )
412 {
413 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
414 }
415
416
417
418 EFI_STATUS
419 EFIAPI
420 PeiPcdSet64Ex (
421 IN CONST EFI_GUID *Guid,
422 IN UINTN ExTokenNumber,
423 IN UINT64 Value
424 )
425 {
426 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
427 }
428
429
430
431 EFI_STATUS
432 EFIAPI
433 PeiPcdSetPtrEx (
434 IN CONST EFI_GUID *Guid,
435 IN UINTN ExTokenNumber,
436 IN UINTN *SizeOfBuffer,
437 IN VOID *Value
438 )
439 {
440 return ExSetWorker (ExTokenNumber, Guid, Value, SizeOfBuffer, TRUE);
441 }
442
443
444
445 EFI_STATUS
446 EFIAPI
447 PeiPcdSetBoolEx (
448 IN CONST EFI_GUID *Guid,
449 IN UINTN ExTokenNumber,
450 IN BOOLEAN Value
451 )
452 {
453 return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
454 }
455
456
457
458
459 EFI_STATUS
460 EFIAPI
461 PeiRegisterCallBackOnSet (
462 IN CONST EFI_GUID *Guid, OPTIONAL
463 IN UINTN ExTokenNumber,
464 IN PCD_PPI_CALLBACK CallBackFunction
465 )
466 {
467 if (!FeaturePcdGet(PcdPeiPcdDatabaseCallbackOnSetEnabled)) {
468 return EFI_UNSUPPORTED;
469 }
470
471 ASSERT (CallBackFunction != NULL);
472
473 return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, TRUE);
474 }
475
476
477
478 EFI_STATUS
479 EFIAPI
480 PcdUnRegisterCallBackOnSet (
481 IN CONST EFI_GUID *Guid, OPTIONAL
482 IN UINTN ExTokenNumber,
483 IN PCD_PPI_CALLBACK CallBackFunction
484 )
485 {
486 if (!FeaturePcdGet(PcdPeiPcdDatabaseCallbackOnSetEnabled)) {
487 return EFI_UNSUPPORTED;
488 }
489
490 ASSERT (CallBackFunction != NULL);
491
492 return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, FALSE);
493 }
494
495
496
497 EFI_STATUS
498 EFIAPI
499 PeiPcdGetNextToken (
500 IN CONST EFI_GUID *Guid, OPTIONAL
501 IN OUT UINTN *TokenNumber
502 )
503 {
504 UINTN GuidTableIdx;
505 PEI_PCD_DATABASE *PeiPcdDb;
506 EFI_GUID *MatchGuid;
507 DYNAMICEX_MAPPING *ExMapTable;
508 UINTN i;
509 BOOLEAN Found;
510 BOOLEAN PeiExMapTableEmpty;
511
512 if (!FeaturePcdGet (PcdPeiPcdDatabaseTraverseEnabled)) {
513 return EFI_UNSUPPORTED;
514 }
515
516 PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
517
518 if (Guid == NULL) {
519 if (*TokenNumber > PEI_NEX_TOKEN_NUMBER) {
520 return EFI_NOT_FOUND;
521 }
522 (*TokenNumber)++;
523 if (*TokenNumber > PEI_NEX_TOKEN_NUMBER) {
524 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
525 }
526 return EFI_SUCCESS;
527 } else {
528 if (PeiExMapTableEmpty) {
529 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
530 return EFI_SUCCESS;
531 }
532
533 //
534 // Assume PCD Database AutoGen tool is sorting the ExMap based on the following order
535 // 1) ExGuid
536 // 2) ExTokenNumber
537 //
538 PeiPcdDb = GetPcdDatabase ();
539
540 MatchGuid = ScanGuid (PeiPcdDb->Init.GuidTable, sizeof(PeiPcdDb->Init.GuidTable), Guid);
541
542 if (MatchGuid == NULL) {
543 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
544 return EFI_NOT_FOUND;
545 }
546
547 GuidTableIdx = MatchGuid - PeiPcdDb->Init.GuidTable;
548
549 ExMapTable = PeiPcdDb->Init.ExMapTable;
550
551 Found = FALSE;
552 //
553 // Locate the GUID in ExMapTable first.
554 //
555 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
556 if (ExMapTable[i].ExGuidIndex == GuidTableIdx) {
557 Found = TRUE;
558 break;
559 }
560 }
561
562 if (Found) {
563 if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
564 *TokenNumber = ExMapTable[i].ExTokenNumber;
565 return EFI_SUCCESS;
566 }
567
568 for ( ; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
569 if (ExMapTable[i].ExTokenNumber == *TokenNumber) {
570 i++;
571 if (i == PEI_EXMAPPING_TABLE_SIZE) {
572 //
573 // Exceed the length of ExMap Table
574 //
575 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
576 return EFI_SUCCESS;
577 }
578 if (ExMapTable[i].ExGuidIndex == GuidTableIdx) {
579 *TokenNumber = ExMapTable[i].ExTokenNumber;
580 return EFI_SUCCESS;
581 } else {
582 *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
583 return EFI_SUCCESS;
584 }
585 }
586 }
587 return EFI_NOT_FOUND;
588 }
589 }
590
591 return EFI_NOT_FOUND;
592 }
593
594
595
596 EFI_STATUS
597 EFIAPI
598 PeiPcdGetNextTokenSpace (
599 IN OUT CONST EFI_GUID **Guid
600 )
601 {
602 UINTN GuidTableIdx;
603 EFI_GUID *MatchGuid;
604 PEI_PCD_DATABASE *PeiPcdDb;
605 DYNAMICEX_MAPPING *ExMapTable;
606 UINTN i;
607 BOOLEAN Found;
608 BOOLEAN PeiExMapTableEmpty;
609
610 if (!FeaturePcdGet (PcdPeiPcdDatabaseTraverseEnabled)) {
611 return EFI_UNSUPPORTED;
612 }
613
614 ASSERT (Guid != NULL);
615
616 PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY;
617
618 if (PeiExMapTableEmpty) {
619 if (*Guid != NULL) {
620 return EFI_NOT_FOUND;
621 } else {
622 return EFI_SUCCESS;
623 }
624 }
625
626 //
627 // Assume PCD Database AutoGen tool is sorting the ExMap based on the following order
628 // 1) ExGuid
629 // 2) ExTokenNumber
630 //
631 PeiPcdDb = GetPcdDatabase ();
632
633 ExMapTable = PeiPcdDb->Init.ExMapTable;
634
635 if (*Guid == NULL) {
636 //
637 // return the first Token Space Guid.
638 //
639 *Guid = &PeiPcdDb->Init.GuidTable[ExMapTable[0].ExGuidIndex];
640 return EFI_SUCCESS;
641 }
642
643 MatchGuid = ScanGuid (PeiPcdDb->Init.GuidTable, sizeof(PeiPcdDb->Init.GuidTable), *Guid);
644
645 if (MatchGuid == NULL) {
646 return EFI_NOT_FOUND;
647 }
648
649 GuidTableIdx = MatchGuid - PeiPcdDb->Init.GuidTable;
650
651 Found = FALSE;
652 for (i = 0; i < PEI_EXMAPPING_TABLE_SIZE; i++) {
653 if (ExMapTable[i].ExGuidIndex == GuidTableIdx) {
654 Found = TRUE;
655 break;
656 }
657 }
658
659 if (Found) {
660 i++;
661 for ( ; i < PEI_EXMAPPING_TABLE_SIZE; i++ ) {
662 if (ExMapTable[i].ExGuidIndex != GuidTableIdx ) {
663 *Guid = &PeiPcdDb->Init.GuidTable[ExMapTable[i].ExGuidIndex];
664 return EFI_SUCCESS;
665 }
666 }
667 *Guid = NULL;
668 return EFI_SUCCESS;
669 }
670
671 return EFI_NOT_FOUND;
672
673 }
674
675 UINTN
676 GetPtrTypeSize (
677 IN UINTN LocalTokenNumberTableIdx,
678 OUT UINTN *MaxSize,
679 IN PEI_PCD_DATABASE *Database
680 )
681 {
682 INTN SizeTableIdx;
683 UINTN LocalTokenNumber;
684 SKU_ID *SkuIdTable;
685 SIZE_INFO *SizeTable;
686 UINTN i;
687
688 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
689
690 LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
691
692 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
693
694 SizeTable = Database->Init.SizeTable;
695
696 *MaxSize = SizeTable[SizeTableIdx];
697 //
698 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
699 // PCD entry.
700 //
701 if (LocalTokenNumber & PCD_TYPE_VPD) {
702 //
703 // We have only one entry for VPD enabled PCD entry:
704 // 1) MAX Size.
705 // We consider current size is equal to MAX size.
706 //
707 return *MaxSize;
708 } else {
709 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
710 //
711 // We have only two entry for Non-Sku enabled PCD entry:
712 // 1) MAX SIZE
713 // 2) Current Size
714 //
715 return SizeTable[SizeTableIdx + 1];
716 } else {
717 //
718 // We have these entry for SKU enabled PCD entry
719 // 1) MAX SIZE
720 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
721 //
722 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, Database);
723 for (i = 0; i < SkuIdTable[0]; i++) {
724 if (SkuIdTable[1 + i] == Database->Init.SystemSkuId) {
725 return SizeTable[SizeTableIdx + 1 + i];
726 }
727 }
728 return SizeTable[SizeTableIdx + 1];
729 }
730 }
731 }
732
733
734
735 BOOLEAN
736 SetPtrTypeSize (
737 IN UINTN LocalTokenNumberTableIdx,
738 IN OUT UINTN *CurrentSize,
739 IN PEI_PCD_DATABASE *Database
740 )
741 {
742 INTN SizeTableIdx;
743 UINTN LocalTokenNumber;
744 SKU_ID *SkuIdTable;
745 SIZE_INFO *SizeTable;
746 UINTN i;
747 UINTN MaxSize;
748
749 SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
750
751 LocalTokenNumber = Database->Init.LocalTokenNumberTable[LocalTokenNumberTableIdx];
752
753 ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
754
755 SizeTable = Database->Init.SizeTable;
756
757 MaxSize = SizeTable[SizeTableIdx];
758 //
759 // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
760 // PCD entry.
761 //
762 if (LocalTokenNumber & PCD_TYPE_VPD) {
763 //
764 // We shouldn't come here as we don't support SET for VPD
765 //
766 ASSERT (FALSE);
767 return FALSE;
768 } else {
769 if ((*CurrentSize > MaxSize) ||
770 (*CurrentSize == MAX_ADDRESS)) {
771 *CurrentSize = MaxSize;
772 return FALSE;
773 }
774
775 if ((LocalTokenNumber & PCD_TYPE_SKU_ENABLED) == 0) {
776 //
777 // We have only two entry for Non-Sku enabled PCD entry:
778 // 1) MAX SIZE
779 // 2) Current Size
780 //
781 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
782 return TRUE;
783 } else {
784 //
785 // We have these entry for SKU enabled PCD entry
786 // 1) MAX SIZE
787 // 2) Current Size for each SKU_ID (It is equal to MaxSku).
788 //
789 SkuIdTable = GetSkuIdArray (LocalTokenNumberTableIdx, Database);
790 for (i = 0; i < SkuIdTable[0]; i++) {
791 if (SkuIdTable[1 + i] == Database->Init.SystemSkuId) {
792 SizeTable[SizeTableIdx + 1 + i] = (SIZE_INFO) *CurrentSize;
793 return TRUE;
794 }
795 }
796 SizeTable[SizeTableIdx + 1] = (SIZE_INFO) *CurrentSize;
797 return TRUE;
798 }
799 }
800
801 }