28 ClusterSize = Clusters->FileSystem->ClusterSize;
30 if (Clusters->Head >= Clusters->Tail) {
31 DEBUG ((DEBUG_INFO,
"NTFS: Compression block overflown\n"));
32 return EFI_VOLUME_CORRUPTED;
37 (Clusters->Elements[Clusters->Head].Lcn - Clusters->Elements[Clusters->Head].Vcn + Clusters->CurrentVcn) * ClusterSize,
41 if (EFI_ERROR (Status)) {
45 ++Clusters->CurrentVcn;
47 if (Clusters->CurrentVcn >= Clusters->Elements[Clusters->Head].Vcn) {
51 Clusters->ClusterOffset = 0;
164 OUT UINT8 *Dest OPTIONAL
168 UINT16 BlockParameters;
172 UINT16 ClearTextPointer;
179 UINT16 BackReference;
182 ASSERT (Clusters != NULL);
185 if (EFI_ERROR (Status)) {
193 ClearTextPointer = 0;
196 while (BlockLength > 0) {
198 DEBUG ((DEBUG_INFO,
"NTFS: Compression block too large\n"));
199 return EFI_VOLUME_CORRUPTED;
204 if (EFI_ERROR (Status)) {
210 if (BlockLength == 0) {
215 if ((TagsByte & 1U) != 0) {
220 if (EFI_ERROR (Status)) {
226 if (ClearTextPointer == 0) {
227 DEBUG ((DEBUG_INFO,
"NTFS: Nontext window empty\n"));
228 return EFI_VOLUME_CORRUPTED;
233 for (Index = ClearTextPointer - 1U; Index >= 0x10U; Index >>= 1U) {
238 Delta = BackReference >> Dshift;
239 Length = (BackReference & Lmask) + 3U;
242 DEBUG ((DEBUG_INFO,
"NTFS: Invalid back-reference.\n"));
243 return EFI_VOLUME_CORRUPTED;
247 DEBUG ((DEBUG_INFO,
"NTFS: (DecompressBlock #1) Buffer overflow.\n"));
248 return EFI_VOLUME_CORRUPTED;
251 for (Index = 0; Index <
Length; ++Index) {
252 Dest[ClearTextPointer] = Dest[ClearTextPointer - Delta - 1U];
262 if (EFI_ERROR (Status)) {
267 DEBUG ((DEBUG_INFO,
"NTFS: (DecompressBlock #2) Buffer overflow.\n"));
268 return EFI_VOLUME_CORRUPTED;
271 Dest[ClearTextPointer++] = PlainText;
285 DEBUG ((DEBUG_INFO,
"NTFS: Invalid compression block size %d\n", BlockLength));
286 return EFI_VOLUME_CORRUPTED;
290 while (BlockLength > 0) {
291 SpareBytes = Clusters->FileSystem->ClusterSize - Clusters->ClusterOffset;
292 if (SpareBytes > BlockLength) {
293 SpareBytes = BlockLength;
296 if ((Dest != NULL) && (SpareBytes != 0)) {
298 DEBUG ((DEBUG_INFO,
"NTFS: (DecompressBlock #3) Buffer overflow.\n"));
299 return EFI_VOLUME_CORRUPTED;
302 CopyMem (Dest, &Clusters->Cluster[Clusters->ClusterOffset], SpareBytes);
307 BlockLength -= SpareBytes;
308 Clusters->ClusterOffset += SpareBytes;
309 if (BlockLength != 0) {
311 if (EFI_ERROR (Status)) {
378 OUT UINT8 *Dest OPTIONAL,
384 UINT64 SpareClusters;
385 UINT64 BlocksPerCluster;
386 UINT64 ClustersPerBlock;
387 UINT64 ClearTextClusters;
392 BlocksPerCluster = 0;
393 ClustersPerBlock = 0;
394 ClusterSize = Runlist->Unit.FileSystem->ClusterSize;
404 while (BlocksTotal != 0) {
405 if ((Runlist->TargetVcn &
UNIT_MASK) == 0) {
406 if ((Runlist->Unit.Head != Runlist->Unit.Tail) && (Runlist->IsSparse == FALSE)) {
407 DEBUG ((DEBUG_INFO,
"NTFS: Invalid compression block\n"));
408 return EFI_VOLUME_CORRUPTED;
411 Runlist->Unit.Head = Runlist->Unit.Tail = 0;
412 Runlist->Unit.CurrentVcn = Runlist->TargetVcn;
413 Runlist->Unit.ClusterOffset = ClusterSize;
414 if (Runlist->TargetVcn >= Runlist->NextVcn) {
416 if (EFI_ERROR (Status)) {
421 while ((Runlist->TargetVcn +
mUnitSize) > Runlist->NextVcn) {
422 if (Runlist->IsSparse) {
426 Runlist->Unit.Elements[Runlist->Unit.Tail].Vcn = Runlist->NextVcn;
427 Runlist->Unit.Elements[Runlist->Unit.Tail].Lcn = Runlist->CurrentLcn + Runlist->NextVcn - Runlist->CurrentVcn;
428 ++Runlist->Unit.Tail;
431 if (EFI_ERROR (Status)) {
438 SpareBlocks = (UINTN)((
mUnitSize - (Runlist->TargetVcn &
UNIT_MASK)) * BlocksPerCluster);
443 if (SpareBlocks > BlocksTotal) {
444 SpareBlocks = BlocksTotal;
447 BlocksTotal -= SpareBlocks;
449 if (Runlist->IsSparse) {
453 Runlist->TargetVcn += SpareBlocks * ClustersPerBlock;
456 if (Runlist->Unit.Tail == 0) {
459 DEBUG ((DEBUG_INFO,
"NTFS: (ReadCompressedBlock #1) Buffer overflow.\n"));
460 return EFI_VOLUME_CORRUPTED;
468 while (SpareBlocks != 0) {
470 if (EFI_ERROR (Status)) {
485 SpareClusters = SpareBlocks * ClustersPerBlock;
488 while ((Runlist->Unit.Head < Runlist->Unit.Tail) && (SpareClusters != 0)) {
489 ClearTextClusters = Runlist->Unit.Elements[Runlist->Unit.Head].Vcn - Runlist->TargetVcn;
490 if (ClearTextClusters > SpareClusters) {
491 ClearTextClusters = SpareClusters;
494 Runlist->TargetVcn += ClearTextClusters;
496 if (
mBufferSize < (ClearTextClusters * ClusterSize)) {
497 DEBUG ((DEBUG_INFO,
"NTFS: (ReadCompressedBlock #2) Buffer overflow.\n"));
498 return EFI_VOLUME_CORRUPTED;
502 Runlist->Unit.FileSystem,
503 Runlist->Unit.Elements[Runlist->Unit.Head].Lcn * ClusterSize,
504 (UINTN)(ClearTextClusters * ClusterSize),
507 if (EFI_ERROR (Status)) {
511 Dest += ClearTextClusters * ClusterSize;
515 SpareClusters -= ClearTextClusters;
516 ++Runlist->Unit.Head;
519 if (SpareClusters != 0) {
522 DEBUG ((DEBUG_INFO,
"NTFS: (ReadCompressedBlock #3) Buffer overflow.\n"));
523 return EFI_VOLUME_CORRUPTED;
527 Runlist->Unit.FileSystem,
528 (Runlist->TargetVcn - Runlist->CurrentVcn + Runlist->CurrentLcn) * ClusterSize,
529 (UINTN)(SpareClusters * ClusterSize),
532 if (EFI_ERROR (Status)) {
536 Dest += SpareClusters * ClusterSize;
540 Runlist->TargetVcn += SpareClusters;
561 UINT64 BlocksPerCluster;
562 UINT64 ClustersPerBlock;
568 ClusterSize = Runlist->Unit.FileSystem->ClusterSize;
570 if (Runlist->Unit.ClearTextBlock != NULL) {
577 CopyMem (Dest, Runlist->Unit.ClearTextBlock + Offset - Runlist->Unit.SavedPosition, Residual);
588 if (Runlist->Unit.ClearTextBlock == NULL) {
589 return EFI_OUT_OF_RESOURCES;
592 Runlist->Unit.SavedPosition = 1U;
595 Vcn = Runlist->TargetVcn;
597 while (Runlist->NextVcn <= Runlist->TargetVcn) {
599 if (EFI_ERROR (Status)) {
600 FreePool (Runlist->Unit.ClearTextBlock);
605 Runlist->Unit.Head = Runlist->Unit.Tail = 0;
606 Runlist->Unit.Cluster = AllocateZeroPool (ClusterSize);
607 if (Runlist->Unit.Cluster == NULL) {
608 FreePool (Runlist->Unit.ClearTextBlock);
609 return EFI_OUT_OF_RESOURCES;
612 if (Vcn > Runlist->TargetVcn) {
618 (UINTN)((Vcn - Runlist->TargetVcn) * BlocksPerCluster)
629 if (EFI_ERROR (Status)) {
630 FreePool (Runlist->Unit.ClearTextBlock);
631 FreePool (Runlist->Unit.Cluster);
637 Target = Runlist->TargetVcn * ClusterSize;
640 if (EFI_ERROR (Status)) {
641 FreePool (Runlist->Unit.ClearTextBlock);
642 FreePool (Runlist->Unit.Cluster);
646 Runlist->Unit.SavedPosition = Target;
650 if (SpareBytes >
Length) {
654 CopyMem (Dest, &Runlist->Unit.ClearTextBlock[Residual], SpareBytes);
655 if (SpareBytes ==
Length) {
656 FreePool (Runlist->Unit.ClearTextBlock);
657 FreePool (Runlist->Unit.Cluster);
666 if (EFI_ERROR (Status)) {
667 FreePool (Runlist->Unit.ClearTextBlock);
668 FreePool (Runlist->Unit.Cluster);
675 Target = Runlist->TargetVcn * ClusterSize;
678 if (EFI_ERROR (Status)) {
679 FreePool (Runlist->Unit.ClearTextBlock);
680 FreePool (Runlist->Unit.Cluster);
684 Runlist->Unit.SavedPosition = Target;
689 FreePool (Runlist->Unit.ClearTextBlock);
690 FreePool (Runlist->Unit.Cluster);