26 if (Vcn >= Runlist->NextVcn) {
28 if (EFI_ERROR (Status)) {
32 return Runlist->CurrentLcn;
35 Delta = Vcn - Runlist->CurrentVcn;
37 return Runlist->IsSparse ? 0 : (Runlist->CurrentLcn + Delta);
53 UINT64 OffsetInsideCluster;
60 ClusterSize = Runlist->Unit.FileSystem->ClusterSize;
61 OffsetInsideCluster = Offset & (ClusterSize - 1U);
65 for (Index = Runlist->TargetVcn; Index < ClustersTotal; ++Index) {
66 Cluster =
GetLcn (Runlist, Index);
67 if (Cluster == (UINT64)(-1)) {
68 return EFI_DEVICE_ERROR;
71 Cluster *= ClusterSize;
73 if (Index == (ClustersTotal - 1U)) {
74 Size = (UINTN)((
Length + Offset) & (ClusterSize - 1U));
80 if (Index != Runlist->TargetVcn) {
81 OffsetInsideCluster = 0;
85 if (Index == Runlist->TargetVcn) {
86 Size -= (UINTN)OffsetInsideCluster;
89 if ((Index != Runlist->TargetVcn) && (Index != (ClustersTotal - 1U))) {
91 OffsetInsideCluster = 0;
96 Runlist->Unit.FileSystem,
97 Cluster + OffsetInsideCluster,
101 if (EFI_ERROR (Status)) {
124 EFI_BLOCK_IO_MEDIA *Media;
126 ASSERT (FileSystem != NULL);
127 ASSERT (FileSystem->DiskIo != NULL);
128 ASSERT (FileSystem->BlockIo != NULL);
130 Media = FileSystem->BlockIo->Media;
132 Status = FileSystem->DiskIo->ReadDisk (
139 if (EFI_ERROR (Status)) {
140 DEBUG ((DEBUG_INFO,
"NTFS: Could not read disk at address %Lx\n", Offset));
151 IN UINT64 RecordNumber
155 UINTN FileRecordSize;
160 FileRecordSize = File->FileSystem->FileRecordSize;
165 RecordNumber * FileRecordSize,
168 if (EFI_ERROR (Status)) {
169 DEBUG ((DEBUG_INFO,
"NTFS: Could not read MFT Record 0x%Lx\n", RecordNumber));
177 SIGNATURE_32 (
'F',
'I',
'L',
'E'),
178 File->FileSystem->SectorSize
203 Current = Attr->Current;
204 if (Current == NULL) {
205 DEBUG ((DEBUG_INFO,
"NTFS: Internal error! Incorrect initialization of attribute iterator\n"));
206 return EFI_VOLUME_CORRUPTED;
209 Attr->Next = Attr->Current;
210 ClusterSize = Attr->BaseMftRecord->File->FileSystem->ClusterSize;
214 DEBUG ((DEBUG_INFO,
"NTFS: $ATTRIBUTE_LIST does not contain even a single record.\n"));
215 return EFI_VOLUME_CORRUPTED;
228 if (Record->
Type != Type) {
237 return EFI_VOLUME_CORRUPTED;
240 Attr->Next = (UINT8 *)Record;
249 if (AttrStart != NULL) {
252 DEBUG ((DEBUG_INFO,
"NTFS: Attribute not found\n"));
253 Status = EFI_VOLUME_CORRUPTED;
256 Attr->Current = Current;
277 UINT64 OffsetInsideCluster;
279 UINTN FileRecordSize;
287 FileRecordSize = Attr->BaseMftRecord->File->FileSystem->FileRecordSize;
288 SectorSize = Attr->BaseMftRecord->File->FileSystem->SectorSize;
289 ClusterSize = Attr->BaseMftRecord->File->FileSystem->ClusterSize;
290 BufferSize = FileRecordSize - (Attr->Current - Attr->BaseMftRecord->FileRecord);
295 DEBUG ((DEBUG_INFO,
"NTFS: (ReadData #1) Attribute is corrupted.\n"));
296 return EFI_VOLUME_CORRUPTED;
303 DEBUG ((DEBUG_INFO,
"NTFS: Read out of range\n"));
304 return EFI_VOLUME_CORRUPTED;
308 DEBUG ((DEBUG_INFO,
"NTFS: Read out of buffer.\n"));
309 return EFI_VOLUME_CORRUPTED;
321 DEBUG ((DEBUG_INFO,
"NTFS: (ReadData #2) Attribute is corrupted.\n"));
322 return EFI_VOLUME_CORRUPTED;
328 if (Runlist == NULL) {
329 return EFI_OUT_OF_RESOURCES;
332 Runlist->
Attr = Attr;
339 DEBUG ((DEBUG_INFO,
"NTFS: Non-Resident Attribute is corrupted.\n"));
341 return EFI_VOLUME_CORRUPTED;
350 DEBUG ((DEBUG_INFO,
"NTFS: Overflow: StartingVCN is too large.\n"));
352 return EFI_VOLUME_CORRUPTED;
356 DEBUG ((DEBUG_INFO,
"NTFS: Read out of range\n"));
358 return EFI_VOLUME_CORRUPTED;
366 DEBUG ((DEBUG_INFO,
"NTFS: Invalid copmression unit size.\n"));
368 return EFI_VOLUME_CORRUPTED;
381 if (EFI_ERROR (Status)) {
383 return EFI_VOLUME_CORRUPTED;
388 OffsetInsideCluster = Offset & (ClusterSize - 1U);
396 Sector1 = Sector0 + 1U;
404 if (EFI_ERROR (Status)) {
406 return EFI_VOLUME_CORRUPTED;
451 if (Signed && (FieldSize != 0) && ((Run[FieldSize - 1U] & 0x80U) != 0)) {
452 Value = (UINT64)(-1);
455 CopyMem (&Value, Run, FieldSize);
483 UINTN FileRecordSize;
487 Run = Runlist->NextDataRun;
488 FileRecordSize = Runlist->Attr->BaseMftRecord->File->FileSystem->FileRecordSize;
489 BufferSize = FileRecordSize - (Run - Runlist->Attr->BaseMftRecord->FileRecord);
492 if (BufferSize == 0) {
493 DEBUG ((DEBUG_INFO,
"NTFS: (ReadRunListElement #1) Runlist is corrupted.\n"));
494 return EFI_VOLUME_CORRUPTED;
497 LengthSize = *Run & 0xFU;
498 OffsetSize = (*Run >> 4U) & 0xFU;
502 if ( (LengthSize > 8U)
504 || ((LengthSize == 0) && (OffsetSize != 0)))
506 DEBUG ((DEBUG_INFO,
"NTFS: (ReadRunListElement #2) Runlist is corrupted.\n"));
507 return EFI_VOLUME_CORRUPTED;
513 if ((LengthSize == 0) && (OffsetSize == 0)) {
514 if ( (Runlist->Attr != NULL)
521 DEBUG ((DEBUG_INFO,
"NTFS: $DATA should be non-resident\n"));
522 return EFI_VOLUME_CORRUPTED;
526 Runlist->CurrentLcn = 0;
532 DEBUG ((DEBUG_INFO,
"NTFS: Run list overflown\n"));
533 return EFI_VOLUME_CORRUPTED;
536 Runlist->CurrentVcn = Runlist->NextVcn;
538 if (BufferSize < LengthSize) {
539 DEBUG ((DEBUG_INFO,
"NTFS: (ReadRunListElement #3) Runlist is corrupted.\n"));
540 return EFI_VOLUME_CORRUPTED;
543 Runlist->NextVcn +=
ReadField (Run, LengthSize, FALSE);
544 if (Runlist->NextVcn <= Runlist->CurrentVcn) {
545 DEBUG ((DEBUG_INFO,
"NTFS: (ReadRunListElement #3.1) Runlist is corrupted.\n"));
546 return EFI_VOLUME_CORRUPTED;
550 BufferSize -= LengthSize;
552 if (BufferSize < OffsetSize) {
553 DEBUG ((DEBUG_INFO,
"NTFS: (ReadRunListElement #4) Runlist is corrupted.\n"));
554 return EFI_VOLUME_CORRUPTED;
557 OffsetLcn =
ReadField (Run, OffsetSize, TRUE);
558 Runlist->CurrentLcn += OffsetLcn;
561 BufferSize -= OffsetSize;
562 Runlist->NextDataRun = Run;
564 Runlist->IsSparse = (OffsetLcn == 0);
582 File->FileRecord = AllocateZeroPool (File->File->FileSystem->FileRecordSize);
583 if (File->FileRecord == NULL) {
587 Status =
ReadMftRecord (File->File, File->FileRecord, File->Inode);
588 if (EFI_ERROR (Status)) {
593 DEBUG ((DEBUG_INFO,
"NTFS: no $SYMLINK in MFT 0x%Lx\n", File->Inode));
597 Status =
ReadAttr (&File->Attr, (UINT8 *)&Symlink, 0, sizeof (Symlink));
598 if (EFI_ERROR (Status)) {
603 switch (Symlink.
Type) {
611 DEBUG ((DEBUG_INFO,
"NTFS: Symlink type invalid (%x)\n", Symlink.
Type));
616 if (Substitute == NULL) {
621 if (EFI_ERROR (Status)) {
623 FreePool (Substitute);
627 for (Letter = Substitute; *Letter != L
'\0'; ++Letter) {
628 if (*Letter == L
'\\') {
EFI_STATUS Decompress(IN RUNLIST *Runlist, IN UINT64 Offset, IN UINTN Length, OUT UINT8 *Dest)
STATIC UINT64 GetLcn(IN OUT RUNLIST *Runlist, IN UINT64 Vcn)
EFI_STATUS EFIAPI ReadAttr(IN NTFS_ATTR *Attr, OUT UINT8 *Dest, IN UINT64 Offset, IN UINTN Length)
EFI_STATUS EFIAPI ReadData(IN NTFS_ATTR *Attr, IN UINT8 *AttrStart, OUT UINT8 *Dest, IN UINT64 Offset, IN UINTN Length)
EFI_STATUS EFIAPI DiskRead(IN EFI_FS *FileSystem, IN UINT64 Offset, IN UINTN Size, IN OUT VOID *Buffer)
EFI_STATUS EFIAPI ReadMftRecord(IN EFI_NTFS_FILE *File, OUT UINT8 *Buffer, IN UINT64 RecordNumber)
STATIC UINT64 ReadField(IN CONST UINT8 *Run, IN UINT8 FieldSize, IN BOOLEAN Signed)
CHAR16 * ReadSymlink(IN NTFS_FILE *File)
STATIC EFI_STATUS ReadClusters(IN RUNLIST *Runlist, IN UINT64 Offset, IN UINTN Length, OUT UINT8 *Dest)
EFI_STATUS EFIAPI ReadRunListElement(IN OUT RUNLIST *Runlist)
UINT8 * LocateAttr(IN NTFS_ATTR *Attr, IN NTFS_FILE *Mft, IN UINT32 Type)
VOID FreeAttr(IN NTFS_ATTR *Attr)
UINT8 * FindAttr(IN NTFS_ATTR *Attr, IN UINT32 Type)
EFI_STATUS EFIAPI Fixup(IN UINT8 *Buffer, IN UINT64 Length, IN UINT32 Magic, IN UINTN SectorSize)
#define COMPRESSION_BLOCK
DMG_SIZE_DEVICE_PATH Size
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
UINT32 EFIAPI WriteUnaligned32(OUT UINT32 *Buffer, IN UINT32 Value)
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
UINT16 CompressionUnitSize