OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
Disc.c
Go to the documentation of this file.
1
9#include "NTFS.h"
10#include "Helper.h"
11
12EFI_STATUS
14 IN EFI_FS *FileSystem,
15 IN CONST CHAR16 *Path,
16 OUT EFI_NTFS_FILE *File,
17 IN FUNCTION_TYPE FunctionType
18 )
19{
20 EFI_STATUS Status;
21 NTFS_FILE *Dir;
22
23 ASSERT (FileSystem != NULL);
24 ASSERT (Path != NULL);
25 ASSERT (File != NULL);
26
27 Dir = NULL;
28
29 CopyMem (&File->RootFile, FileSystem->RootIndex, sizeof (File->RootFile));
30 CopyMem (&File->MftFile, FileSystem->MftStart, sizeof (File->MftFile));
31
32 Status = FsHelpFindFile (
33 Path,
34 &File->RootFile,
35 &Dir,
37 );
38 if (EFI_ERROR (Status)) {
39 return Status;
40 }
41
42 Status = IterateDir (Dir, File, FunctionType);
43
44 if (Dir != &File->RootFile) {
45 FreeFile (Dir);
46 FreePool (Dir);
47 }
48
49 return Status;
50}
51
52EFI_STATUS
54 IN EFI_NTFS_FILE *File
55 )
56{
57 EFI_STATUS Status;
58 NTFS_FILE *BaseMftRecord;
59
60 ASSERT (File != NULL);
61
62 BaseMftRecord = NULL;
63
64 CopyMem (&File->RootFile, File->FileSystem->RootIndex, sizeof (File->RootFile));
65 CopyMem (&File->MftFile, File->FileSystem->MftStart, sizeof (File->MftFile));
66
67 Status = FsHelpFindFile (
68 File->Path,
69 &File->RootFile,
70 &BaseMftRecord,
72 );
73 if (EFI_ERROR (Status)) {
74 return Status;
75 }
76
77 if (BaseMftRecord != &File->RootFile) {
78 CopyMem (&File->RootFile, BaseMftRecord, sizeof (*BaseMftRecord));
79
80 if (!File->RootFile.InodeRead) {
81 Status = InitFile (&File->RootFile, File->RootFile.Inode);
82 }
83
84 FreeFile (BaseMftRecord);
85 FreePool (BaseMftRecord);
86 }
87
88 File->Offset = 0;
89
90 return Status;
91}
92
93EFI_STATUS
95 IN EFI_FS *FileSystem
96 )
97{
98 EFI_STATUS Status;
99 BOOT_FILE_DATA Boot;
100 UINTN Size;
101 EFI_NTFS_FILE *RootFile;
102
103 ASSERT (FileSystem != NULL);
104
105 Status = DiskRead (FileSystem, 0, sizeof (Boot), &Boot);
106 if (EFI_ERROR (Status)) {
107 return Status;
108 }
109
110 if ( (Boot.SystemId[0] != SIGNATURE_32 ('N', 'T', 'F', 'S'))
111 || (Boot.SectorsPerCluster == 0)
112 || ((Boot.SectorsPerCluster & (Boot.SectorsPerCluster - 1U)) != 0)
113 || (Boot.BytesPerSector == 0)
114 || ((Boot.BytesPerSector & (Boot.BytesPerSector - 1U)) != 0))
115 {
116 DEBUG ((DEBUG_INFO, "NTFS: (NtfsMount #1) BIOS Parameter Block is corrupted.\n"));
117 return EFI_VOLUME_CORRUPTED;
118 }
119
120 FileSystem->SectorSize = (UINTN)Boot.BytesPerSector;
121 FileSystem->ClusterSize = (UINTN)Boot.SectorsPerCluster * FileSystem->SectorSize;
122
123 if (Boot.MftRecordClusters > 0) {
124 Size = (UINTN)Boot.MftRecordClusters * FileSystem->ClusterSize;
125 } else if (-Boot.MftRecordClusters >= 31) {
126 DEBUG ((DEBUG_INFO, "NTFS: (NtfsMount #2) BIOS Parameter Block is corrupted.\n"));
127 return EFI_VOLUME_CORRUPTED;
128 } else {
129 Size = (UINTN)LShiftU64 (1ULL, -Boot.MftRecordClusters);
130 }
131
132 FileSystem->FileRecordSize = Size;
133 if (FileSystem->FileRecordSize < FileSystem->SectorSize) {
134 DEBUG ((DEBUG_INFO, "NTFS: File Record is smaller than Sector.\n"));
135 return EFI_VOLUME_CORRUPTED;
136 }
137
138 if (Boot.IndexRecordClusters > 0) {
139 Size = (UINTN)Boot.IndexRecordClusters * FileSystem->ClusterSize;
140 } else if (-Boot.IndexRecordClusters >= 31) {
141 DEBUG ((DEBUG_INFO, "NTFS: (NtfsMount #3) BIOS Parameter Block is corrupted.\n"));
142 return EFI_VOLUME_CORRUPTED;
143 } else {
144 Size = (UINTN)LShiftU64 (1ULL, -Boot.IndexRecordClusters);
145 }
146
147 FileSystem->IndexRecordSize = Size;
148 if (FileSystem->IndexRecordSize < FileSystem->SectorSize) {
149 DEBUG ((DEBUG_INFO, "NTFS: Index Record is smaller than Sector.\n"));
150 return EFI_VOLUME_CORRUPTED;
151 }
152
153 FileSystem->FirstMftRecord = Boot.MftLcn * FileSystem->ClusterSize;
154 //
155 // Driver limitations
156 //
157 if ( (FileSystem->FileRecordSize > NTFS_MAX_MFT)
158 || (FileSystem->IndexRecordSize > NTFS_MAX_IDX))
159 {
160 DEBUG ((DEBUG_INFO, "NTFS: (NtfsMount #4) BIOS Parameter Block is corrupted.\n"));
161 return EFI_VOLUME_CORRUPTED;
162 }
163
164 RootFile = AllocateZeroPool (sizeof (*RootFile));
165 if (RootFile == NULL) {
166 return EFI_OUT_OF_RESOURCES;
167 }
168
169 CopyMem (RootFile, &FileSystem->EfiFile, sizeof (FileSystem->EfiFile));
170
171 RootFile->IsDir = TRUE;
172 RootFile->Path = L"/";
173 RootFile->RefCount = 1U;
174 RootFile->FileSystem = FileSystem;
175 RootFile->RootFile.File = RootFile;
176 RootFile->MftFile.File = RootFile;
177
178 RootFile->MftFile.FileRecord = AllocateZeroPool (FileSystem->FileRecordSize);
179 if (RootFile->MftFile.FileRecord == NULL) {
180 FreePool (RootFile);
181 return EFI_OUT_OF_RESOURCES;
182 }
183
184 Status = DiskRead (
185 FileSystem,
186 FileSystem->FirstMftRecord,
187 FileSystem->FileRecordSize,
188 RootFile->MftFile.FileRecord
189 );
190 if (EFI_ERROR (Status)) {
191 FreePool (RootFile->MftFile.FileRecord);
192 FreePool (RootFile);
193 return Status;
194 }
195
196 Status = Fixup (
197 RootFile->MftFile.FileRecord,
198 FileSystem->FileRecordSize,
199 SIGNATURE_32 ('F', 'I', 'L', 'E'),
200 FileSystem->SectorSize
201 );
202 if (EFI_ERROR (Status)) {
203 FreePool (RootFile->MftFile.FileRecord);
204 FreePool (RootFile);
205 return Status;
206 }
207
208 if (LocateAttr (&RootFile->MftFile.Attr, &RootFile->MftFile, AT_DATA) == NULL) {
209 FreePool (RootFile->MftFile.FileRecord);
210 FreePool (RootFile);
211 return EFI_VOLUME_CORRUPTED;
212 }
213
214 Status = InitFile (&RootFile->RootFile, ROOT_FILE);
215 if (EFI_ERROR (Status)) {
216 FreePool (RootFile->MftFile.FileRecord);
217 FreePool (RootFile);
218 return Status;
219 }
220
221 FileSystem->RootIndex = &RootFile->RootFile;
222 FileSystem->MftStart = &RootFile->MftFile;
223
224 return EFI_SUCCESS;
225}
226
240EFI_STATUS
241EFIAPI
243 IN UINT8 *Buffer,
244 IN UINT64 Length,
245 IN UINT32 Magic,
246 IN UINTN SectorSize
247 )
248{
249 FILE_RECORD_HEADER *Record;
250 UINT8 *UpdateSequencePointer;
251 UINT16 UpdateSequenceNumber;
252 UINT64 USCounter;
253 UINT8 *BufferEnd;
254
255 ASSERT (Buffer != NULL);
256
257 Record = (FILE_RECORD_HEADER *)Buffer;
258
259 if (Length < sizeof (*Record)) {
260 DEBUG ((DEBUG_INFO, "NTFS: (Fixup #1) Record is corrupted.\n"));
261 return EFI_VOLUME_CORRUPTED;
262 }
263
264 if (Record->Magic != Magic) {
265 DEBUG ((DEBUG_INFO, "NTFS: (Fixup #2) Record is corrupted.\n"));
266 return EFI_NOT_FOUND;
267 }
268
269 if ((Record->UpdateSequenceOffset + sizeof (UINT16)) > Length) {
270 DEBUG ((DEBUG_INFO, "NTFS: (Fixup #3) Record is corrupted.\n"));
271 return EFI_VOLUME_CORRUPTED;
272 }
273
274 if (((UINT64)Record->S_Size - 1U) != DivU64x64Remainder (Length, SectorSize, NULL)) {
275 DEBUG ((DEBUG_INFO, "NTFS: (Fixup #4) Record is corrupted.\n"));
276 return EFI_VOLUME_CORRUPTED;
277 }
278
279 UpdateSequencePointer = Buffer + Record->UpdateSequenceOffset;
280 UpdateSequenceNumber = ReadUnaligned16 ((UINT16 *)UpdateSequencePointer);
281 USCounter = Record->UpdateSequenceOffset;
282
283 if (Length < (SectorSize - sizeof (UINT16))) {
284 DEBUG ((DEBUG_INFO, "NTFS: (Fixup #5) Record is corrupted.\n"));
285 return EFI_VOLUME_CORRUPTED;
286 }
287
288 BufferEnd = Buffer + Length;
289 Buffer += SectorSize - sizeof (UINT16);
290 while ((Buffer + sizeof (UINT16)) <= BufferEnd) {
291 UpdateSequencePointer += sizeof (UINT16);
292
293 USCounter += sizeof (UINT16);
294 if ((USCounter + sizeof (UINT16)) > Length) {
295 DEBUG ((DEBUG_INFO, "NTFS: (Fixup #6) Record is corrupted.\n"));
296 return EFI_VOLUME_CORRUPTED;
297 }
298
299 if (ReadUnaligned16 ((UINT16 *)Buffer) != UpdateSequenceNumber) {
300 DEBUG ((DEBUG_INFO, "NTFS: (Fixup #7) Record is corrupted.\n"));
301 return EFI_VOLUME_CORRUPTED;
302 }
303
304 Buffer[0] = UpdateSequencePointer[0];
305 Buffer[1] = UpdateSequencePointer[1];
306 Buffer += SectorSize;
307 }
308
309 return EFI_SUCCESS;
310}
311
312EFI_STATUS
314 OUT NTFS_ATTR *Attr,
315 IN NTFS_FILE *File
316 )
317{
318 FILE_RECORD_HEADER *Record;
319 UINT64 AttrEnd;
320
321 ASSERT (Attr != NULL);
322 ASSERT (File != NULL);
323
324 Record = (FILE_RECORD_HEADER *)File->FileRecord;
325
326 Attr->BaseMftRecord = File;
327 Attr->Flags = (File == &File->File->MftFile) ? NTFS_AF_MFT_FILE : 0;
328
329 AttrEnd = Record->AttributeOffset + sizeof (ATTR_HEADER_RES);
330 if ( (AttrEnd > File->File->FileSystem->FileRecordSize)
331 || (AttrEnd > Record->RealSize)
332 || (Record->RealSize > Record->AllocatedSize))
333 {
334 DEBUG ((DEBUG_INFO, "NTFS: (InitAttr) File record is corrupted.\n"));
335 return EFI_VOLUME_CORRUPTED;
336 }
337
338 Attr->Next = File->FileRecord + Record->AttributeOffset;
339 Attr->Last = NULL;
340 Attr->ExtensionMftRecord = NULL;
341 Attr->NonResAttrList = NULL;
342
343 return EFI_SUCCESS;
344}
345
346UINT8 *
348 IN NTFS_ATTR *Attr,
349 IN NTFS_FILE *Mft,
350 IN UINT32 Type
351 )
352{
353 EFI_STATUS Status;
354 UINT8 *AttrStart;
355
356 ASSERT (Attr != NULL);
357 ASSERT (Mft != NULL);
358
359 Status = InitAttr (Attr, Mft);
360 if (EFI_ERROR (Status)) {
361 return NULL;
362 }
363
364 AttrStart = FindAttr (Attr, Type);
365 if (AttrStart == NULL) {
366 FreeAttr (Attr);
367 return NULL;
368 }
369
370 if ((Attr->Flags & NTFS_AF_ALST) == 0) {
371 while (TRUE) {
372 AttrStart = FindAttr (Attr, Type);
373 if (AttrStart == NULL) {
374 break;
375 }
376
377 if ((Attr->Flags & NTFS_AF_ALST) != 0) {
378 return AttrStart;
379 }
380 }
381
382 FreeAttr (Attr);
383
384 Status = InitAttr (Attr, Mft);
385 if (EFI_ERROR (Status)) {
386 return NULL;
387 }
388
389 AttrStart = FindAttr (Attr, Type);
390 if (AttrStart == NULL) {
391 FreeAttr (Attr);
392 return NULL;
393 }
394 }
395
396 return AttrStart;
397}
398
399UINT8 *
401 IN NTFS_ATTR *Attr,
402 IN UINT32 Type
403 )
404{
405 EFI_STATUS Status;
406 UINT8 *AttrStart;
407 ATTR_HEADER_RES *Res;
408 ATTR_HEADER_NONRES *NonRes;
409 ATTR_LIST_RECORD *LRecord;
410 FILE_RECORD_HEADER *FRecord;
411 UINT64 BufferSize;
412 UINTN FileRecordSize;
413 UINTN SectorSize;
414
415 ASSERT (Attr != NULL);
416
417 BufferSize = 0;
418 FileRecordSize = Attr->BaseMftRecord->File->FileSystem->FileRecordSize;
419 SectorSize = Attr->BaseMftRecord->File->FileSystem->SectorSize;
420
421 if ((Attr->Flags & NTFS_AF_ALST) != 0) {
422retry:
423 while ((Attr->Next + sizeof (*LRecord)) <= Attr->Last) {
424 Attr->Current = Attr->Next;
425 LRecord = (ATTR_LIST_RECORD *)Attr->Current;
426
427 if (BufferSize < LRecord->RecordLength) {
428 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #0) $ATTRIBUTE_LIST is corrupted.\n"));
429 FreeAttr (Attr);
430 return NULL;
431 }
432
433 Attr->Next += LRecord->RecordLength;
434 BufferSize -= LRecord->RecordLength;
435 if (Attr->Next <= Attr->Current) {
436 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #1) $ATTRIBUTE_LIST is corrupted.\n"));
437 FreeAttr (Attr);
438 return NULL;
439 }
440
441 if ((LRecord->Type == Type) || (Type == 0)) {
442 if (Attr->Flags & NTFS_AF_MFT_FILE) {
443 Status = DiskRead (
444 Attr->BaseMftRecord->File->FileSystem,
445 ReadUnaligned32 ((UINT32 *)(Attr->Current + 0x10U)),
446 FileRecordSize / 2U,
447 Attr->ExtensionMftRecord
448 );
449 if (EFI_ERROR (Status)) {
450 DEBUG ((DEBUG_INFO, "NTFS: Could not read first part of extension record.\n"));
451 FreeAttr (Attr);
452 return NULL;
453 }
454
455 Status = DiskRead (
456 Attr->BaseMftRecord->File->FileSystem,
457 ReadUnaligned32 ((UINT32 *)(Attr->Current + 0x14U)),
458 FileRecordSize / 2U,
459 Attr->ExtensionMftRecord + FileRecordSize / 2U
460 );
461 if (EFI_ERROR (Status)) {
462 DEBUG ((DEBUG_INFO, "NTFS: Could not read second part of extension record.\n"));
463 FreeAttr (Attr);
464 return NULL;
465 }
466
467 Status = Fixup (
468 Attr->ExtensionMftRecord,
469 FileRecordSize,
470 SIGNATURE_32 ('F', 'I', 'L', 'E'),
471 Attr->BaseMftRecord->File->FileSystem->SectorSize
472 );
473 if (EFI_ERROR (Status)) {
474 DEBUG ((DEBUG_INFO, "NTFS: Fixup failed.\n"));
475 FreeAttr (Attr);
476 return NULL;
477 }
478 } else {
479 Status = ReadMftRecord (
480 Attr->BaseMftRecord->File,
481 Attr->ExtensionMftRecord,
482 (UINT32)LRecord->BaseFileReference
483 );
484 if (EFI_ERROR (Status)) {
485 DEBUG ((DEBUG_INFO, "NTFS: Could not read extension record.\n"));
486 FreeAttr (Attr);
487 return NULL;
488 }
489 }
490
491 FRecord = (FILE_RECORD_HEADER *)Attr->ExtensionMftRecord;
492 BufferSize = FileRecordSize;
493 if ((FRecord->AttributeOffset + sizeof (*Res)) <= BufferSize) {
494 Res = (ATTR_HEADER_RES *)((UINT8 *)FRecord + FRecord->AttributeOffset);
495 BufferSize -= FRecord->AttributeOffset;
496 } else {
497 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #1) Extension record is corrupted.\n"));
498 FreeAttr (Attr);
499 return NULL;
500 }
501
502 while ((BufferSize >= sizeof (UINT32)) && (Res->Type != ATTRIBUTES_END_MARKER)) {
503 if (BufferSize < sizeof (*Res)) {
504 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #2) Extension record is corrupted.\n"));
505 FreeAttr (Attr);
506 return NULL;
507 }
508
509 if ( (Res->Type == LRecord->Type)
510 && (Res->AttributeId == LRecord->AttributeId))
511 {
512 return (UINT8 *)Res;
513 }
514
515 if ((Res->Length == 0) || (Res->Length >= BufferSize)) {
516 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #3) Extension record is corrupted.\n"));
517 FreeAttr (Attr);
518 return NULL;
519 }
520
521 BufferSize -= Res->Length;
522 Res = (ATTR_HEADER_RES *)((UINT8 *)Res + Res->Length);
523 }
524
525 DEBUG ((DEBUG_INFO, "NTFS: Can\'t find 0x%X in attribute list\n", Attr->Current));
526 FreeAttr (Attr);
527 return NULL;
528 }
529 }
530
531 FreeAttr (Attr);
532 return NULL;
533 }
534
535 Attr->Current = Attr->Next;
536 Res = (ATTR_HEADER_RES *)Attr->Current;
537 BufferSize = FileRecordSize - (Attr->Current - Attr->BaseMftRecord->FileRecord);
538
539 while ((BufferSize >= sizeof (UINT32)) && (Res->Type != ATTRIBUTES_END_MARKER)) {
540 if (BufferSize < sizeof (*Res)) {
541 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #1) File record is corrupted.\n"));
542 FreeAttr (Attr);
543 return NULL;
544 }
545
546 if ((Res->Length == 0) || (Res->Length >= BufferSize)) {
547 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #2) File record is corrupted.\n"));
548 FreeAttr (Attr);
549 return NULL;
550 }
551
552 BufferSize -= Res->Length;
553 Attr->Next += Res->Length;
554
555 if (Res->Type == AT_ATTRIBUTE_LIST) {
556 Attr->Last = Attr->Current;
557 }
558
559 if ((Res->Type == Type) || (Type == 0)) {
560 return Attr->Current;
561 }
562
563 Attr->Current = Attr->Next;
564 Res = (ATTR_HEADER_RES *)Attr->Current;
565 }
566
567 //
568 // Continue search in $ATTRIBUTE_LIST
569 //
570 if (Attr->Last != NULL) {
571 if (Attr->ExtensionMftRecord != NULL) {
572 FreePool (Attr->ExtensionMftRecord);
573 }
574
575 Attr->ExtensionMftRecord = AllocateZeroPool (FileRecordSize);
576 if (Attr->ExtensionMftRecord == NULL) {
577 FreeAttr (Attr);
578 return NULL;
579 }
580
581 AttrStart = Attr->Last;
582 Res = (ATTR_HEADER_RES *)Attr->Last;
583 BufferSize = FileRecordSize - (Attr->Last - Attr->BaseMftRecord->FileRecord);
584
585 if (BufferSize < sizeof (*Res)) {
586 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #3) File record is corrupted.\n"));
587 FreeAttr (Attr);
588 return NULL;
589 }
590
591 if (Res->NonResFlag != 0) {
592 NonRes = (ATTR_HEADER_NONRES *)Res;
593 Attr->Current = (UINT8 *)NonRes;
594
595 if (BufferSize < sizeof (*NonRes)) {
596 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #4) File record is corrupted.\n"));
597 FreeAttr (Attr);
598 return NULL;
599 }
600
601 if (NonRes->RealSize > MAX_FILE_SIZE) {
602 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr) File is too huge.\n"));
603 FreeAttr (Attr);
604 return NULL;
605 }
606
607 if (Attr->NonResAttrList != NULL) {
608 FreePool (Attr->NonResAttrList);
609 }
610
611 Attr->NonResAttrList = AllocateZeroPool ((UINTN)NonRes->RealSize);
612 if (Attr->NonResAttrList == NULL) {
613 FreeAttr (Attr);
614 return NULL;
615 }
616
617 Status = ReadData (Attr, AttrStart, Attr->NonResAttrList, 0, (UINTN)NonRes->RealSize);
618 if (EFI_ERROR (Status)) {
619 DEBUG ((DEBUG_INFO, "NTFS: Failed to read non-resident attribute list\n"));
620 FreeAttr (Attr);
621 return NULL;
622 }
623
624 Attr->Next = Attr->NonResAttrList;
625 Attr->Last = Attr->NonResAttrList + NonRes->RealSize;
626 BufferSize = NonRes->RealSize;
627 } else {
628 if ((Res->InfoOffset < Res->Length) && (Res->Length <= BufferSize)) {
629 Attr->Next = (UINT8 *)Res + Res->InfoOffset;
630 Attr->Last = (UINT8 *)Res + Res->Length;
631 BufferSize -= Res->InfoOffset;
632 } else {
633 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #5) File record is corrupted.\n"));
634 FreeAttr (Attr);
635 return NULL;
636 }
637 }
638
639 Attr->Flags |= NTFS_AF_ALST;
640 LRecord = (ATTR_LIST_RECORD *)Attr->Next;
641 while ((Attr->Next + sizeof (*LRecord)) < Attr->Last) {
642 if ((LRecord->Type == Type) || (Type == 0)) {
643 break;
644 }
645
646 if (BufferSize < LRecord->RecordLength) {
647 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #2) $ATTRIBUTE_LIST is corrupted.\n"));
648 FreeAttr (Attr);
649 return NULL;
650 }
651
652 if (LRecord->RecordLength == 0) {
653 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #3) $ATTRIBUTE_LIST is corrupted.\n"));
654 FreeAttr (Attr);
655 return NULL;
656 }
657
658 Attr->Next += LRecord->RecordLength;
659 BufferSize -= LRecord->RecordLength;
660 LRecord = (ATTR_LIST_RECORD *)Attr->Next;
661 }
662
663 if ((Attr->Next + sizeof (*LRecord)) >= Attr->Last) {
664 FreeAttr (Attr);
665 return NULL;
666 }
667
668 if ((Attr->Flags & NTFS_AF_MFT_FILE) && (Type == AT_DATA)) {
669 Attr->Flags |= NTFS_AF_GPOS;
670 Attr->Current = Attr->Next;
671 AttrStart = Attr->Current;
672
673 if (BufferSize >= 0x18U) {
675 (UINT32 *)(AttrStart + 0x10U),
676 (UINT32)DivU64x64Remainder (Attr->BaseMftRecord->File->FileSystem->FirstMftRecord, SectorSize, NULL)
677 );
679 (UINT32 *)(AttrStart + 0x14U),
680 (UINT32)DivU64x64Remainder (Attr->BaseMftRecord->File->FileSystem->FirstMftRecord, SectorSize, NULL) + 1U
681 );
682 } else {
683 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #7) File record is corrupted.\n"));
684 FreeAttr (Attr);
685 return NULL;
686 }
687
688 AttrStart = Attr->Next + ReadUnaligned16 ((UINT16 *)(AttrStart + 0x04U));
689 while ((AttrStart + sizeof (UINT32) + sizeof (UINT16)) < Attr->Last) {
690 if (ReadUnaligned32 ((UINT32 *)AttrStart) != Type) {
691 break;
692 }
693
694 Status = ReadAttr (
695 Attr,
696 AttrStart + 0x10U,
697 ReadUnaligned32 ((UINT32 *)(AttrStart + 0x10U)) * FileRecordSize,
698 FileRecordSize
699 );
700 if (EFI_ERROR (Status)) {
701 FreeAttr (Attr);
702 return NULL;
703 }
704
705 if (ReadUnaligned16 ((UINT16 *)(AttrStart + 4U)) == 0) {
706 DEBUG ((DEBUG_INFO, "NTFS: (FindAttr #8) File record is corrupted.\n"));
707 FreeAttr (Attr);
708 return NULL;
709 }
710
711 AttrStart += ReadUnaligned16 ((UINT16 *)(AttrStart + 4U));
712 }
713
714 Attr->Next = Attr->Current;
715 Attr->Flags &= ~NTFS_AF_GPOS;
716 }
717
718 goto retry;
719 }
720
721 FreeAttr (Attr);
722 return NULL;
723}
724
725EFI_STATUS
726EFIAPI
728 IN OUT NTFS_FILE *File,
729 IN UINT64 RecordNumber
730 )
731{
732 EFI_STATUS Status;
733 ATTR_HEADER_RES *Attr;
734 FILE_RECORD_HEADER *Record;
735
736 ASSERT (File != NULL);
737
738 File->InodeRead = TRUE;
739
740 File->FileRecord = AllocateZeroPool (File->File->FileSystem->FileRecordSize);
741 if (File->FileRecord == NULL) {
742 return EFI_OUT_OF_RESOURCES;
743 }
744
745 Status = ReadMftRecord (File->File, File->FileRecord, RecordNumber);
746 if (EFI_ERROR (Status)) {
747 FreePool (File->FileRecord);
748 File->FileRecord = NULL;
749 return Status;
750 }
751
752 Record = (FILE_RECORD_HEADER *)File->FileRecord;
753
754 if ((Record->Flags & IS_IN_USE) == 0) {
755 DEBUG ((DEBUG_INFO, "NTFS: MFT Record 0x%Lx is not in use\n", RecordNumber));
756 FreePool (File->FileRecord);
757 File->FileRecord = NULL;
758 return EFI_VOLUME_CORRUPTED;
759 }
760
761 if ((Record->Flags & IS_A_DIRECTORY) == 0) {
762 Attr = (ATTR_HEADER_RES *)LocateAttr (&File->Attr, File, AT_DATA);
763 if (Attr == NULL) {
764 DEBUG ((DEBUG_INFO, "NTFS: No $DATA in MFT Record 0x%Lx\n", RecordNumber));
765 FreePool (File->FileRecord);
766 File->FileRecord = NULL;
767 return EFI_VOLUME_CORRUPTED;
768 }
769
770 if (Attr->NonResFlag == 0) {
771 File->DataAttributeSize = Attr->InfoLength;
772 } else {
773 File->DataAttributeSize = ((ATTR_HEADER_NONRES *)Attr)->RealSize;
774 }
775
776 if ((File->Attr.Flags & NTFS_AF_ALST) == 0) {
777 File->Attr.Last = 0;
778 }
779 } else {
780 Status = InitAttr (&File->Attr, File);
781 if (EFI_ERROR (Status)) {
782 FreePool (File->FileRecord);
783 File->FileRecord = NULL;
784 return Status;
785 }
786 }
787
788 return EFI_SUCCESS;
789}
790
791VOID
793 IN NTFS_ATTR *Attr
794 )
795{
796 ASSERT (Attr != NULL);
797
798 if (Attr->ExtensionMftRecord != NULL) {
799 FreePool (Attr->ExtensionMftRecord);
800 Attr->ExtensionMftRecord = NULL;
801 }
802
803 if (Attr->NonResAttrList != NULL) {
804 FreePool (Attr->NonResAttrList);
805 Attr->NonResAttrList = NULL;
806 }
807}
808
809VOID
811 IN NTFS_FILE *File
812 )
813{
814 ASSERT (File != NULL);
815
816 FreeAttr (&File->Attr);
817
818 if ( (File->FileRecord != NULL)
819 && (File->FileRecord != File->File->FileSystem->RootIndex->FileRecord)
820 && (File->FileRecord != File->File->FileSystem->MftStart->FileRecord))
821 {
822 FreePool (File->FileRecord);
823 File->FileRecord = NULL;
824 }
825}
UINT64 Length
EFI_STATUS EFIAPI ReadAttr(IN NTFS_ATTR *Attr, OUT UINT8 *Dest, IN UINT64 Offset, IN UINTN Length)
Definition Data.c:184
EFI_STATUS EFIAPI ReadData(IN NTFS_ATTR *Attr, IN UINT8 *AttrStart, OUT UINT8 *Dest, IN UINT64 Offset, IN UINTN Length)
Definition Data.c:258
EFI_STATUS EFIAPI DiskRead(IN EFI_FS *FileSystem, IN UINT64 Offset, IN UINTN Size, IN OUT VOID *Buffer)
Definition Data.c:116
EFI_STATUS EFIAPI ReadMftRecord(IN EFI_NTFS_FILE *File, OUT UINT8 *Buffer, IN UINT64 RecordNumber)
Definition Data.c:148
UINT8 * LocateAttr(IN NTFS_ATTR *Attr, IN NTFS_FILE *Mft, IN UINT32 Type)
Definition Disc.c:347
VOID FreeFile(IN NTFS_FILE *File)
Definition Disc.c:810
EFI_STATUS NtfsDir(IN EFI_FS *FileSystem, IN CONST CHAR16 *Path, OUT EFI_NTFS_FILE *File, IN FUNCTION_TYPE FunctionType)
Definition Disc.c:13
VOID FreeAttr(IN NTFS_ATTR *Attr)
Definition Disc.c:792
EFI_STATUS InitAttr(OUT NTFS_ATTR *Attr, IN NTFS_FILE *File)
Definition Disc.c:313
UINT8 * FindAttr(IN NTFS_ATTR *Attr, IN UINT32 Type)
Definition Disc.c:400
EFI_STATUS EFIAPI Fixup(IN UINT8 *Buffer, IN UINT64 Length, IN UINT32 Magic, IN UINTN SectorSize)
Definition Disc.c:242
EFI_STATUS NtfsOpen(IN EFI_NTFS_FILE *File)
Definition Disc.c:53
EFI_STATUS NtfsMount(IN EFI_FS *FileSystem)
Definition Disc.c:94
EFI_STATUS EFIAPI InitFile(IN OUT NTFS_FILE *File, IN UINT64 RecordNumber)
Definition Disc.c:727
@ IS_IN_USE
Definition Driver.h:188
@ IS_A_DIRECTORY
Definition Driver.h:189
#define ATTRIBUTES_END_MARKER
Definition Driver.h:19
@ NTFS_AF_MFT_FILE
Definition Driver.h:171
@ NTFS_AF_ALST
Definition Driver.h:170
@ NTFS_AF_GPOS
Definition Driver.h:172
#define MAX_FILE_SIZE
Definition Driver.h:20
#define NTFS_MAX_MFT
Definition Driver.h:12
#define NTFS_MAX_IDX
Definition Driver.h:13
@ AT_ATTRIBUTE_LIST
Definition Driver.h:115
@ AT_DATA
Definition Driver.h:121
@ ROOT_FILE
Definition Driver.h:161
FUNCTION_TYPE
Definition Helper.h:54
@ FSHELP_DIR
Definition Helper.h:31
@ FSHELP_REG
Definition Helper.h:30
EFI_STATUS IterateDir(IN NTFS_FILE *dir, IN VOID *FileOrCtx, IN FUNCTION_TYPE FunctionType)
Definition Index.c:534
EFI_STATUS FsHelpFindFile(IN CONST CHAR16 *Path, IN NTFS_FILE *RootNode, OUT NTFS_FILE **FoundNode, IN FSHELP_FILETYPE Type)
Definition Index.c:471
DMG_SIZE_DEVICE_PATH Size
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
UINT16 EFIAPI ReadUnaligned16(IN CONST UINT16 *Buffer)
UINT32 EFIAPI WriteUnaligned32(OUT UINT32 *Buffer, IN UINT32 Value)
UINT32 EFIAPI ReadUnaligned32(IN CONST UINT32 *Buffer)
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
Definition UserMath.c:59
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition UserMath.c:76
#define ASSERT(x)
Definition coder.h:55
NTFS_FILE RootFile
Definition Driver.h:634
UINT32 RefCount
Definition Driver.h:633
BOOLEAN IsDir
Definition Driver.h:628
CHAR16 * Path
Definition Driver.h:630
EFI_FS * FileSystem
Definition Driver.h:636
EFI_FILE_PROTOCOL EfiFile
Definition Driver.h:627
NTFS_FILE MftFile
Definition Driver.h:635
NTFS_ATTR Attr
Definition Driver.h:622
UINT8 * FileRecord
Definition Driver.h:615
EFI_NTFS_FILE * File
Definition Driver.h:623
UINT16 InfoOffset
Definition Driver.h:293
UINT32 InfoLength
Definition Driver.h:292
UINT16 AttributeId
Definition Driver.h:291
UINT32 Type
Definition Driver.h:285
UINT32 Length
Definition Driver.h:286
UINT8 NonResFlag
Definition Driver.h:287
UINT64 BaseFileReference
Definition Driver.h:362
UINT16 AttributeId
Definition Driver.h:363
UINT16 RecordLength
Definition Driver.h:358
INT8 MftRecordClusters
Definition Driver.h:559
UINT64 MftLcn
Definition Driver.h:557
UINT16 BytesPerSector
Definition Driver.h:547
INT8 IndexRecordClusters
Definition Driver.h:561
UINT8 SectorsPerCluster
Definition Driver.h:548
UINT32 SystemId[2]
Definition Driver.h:546
UINT32 AllocatedSize
Definition Driver.h:259
UINT16 UpdateSequenceOffset
Definition Driver.h:251
UINT16 AttributeOffset
Definition Driver.h:256