Skip to content

Commit b81bc0d

Browse files
committed
[FREELDR] Add Extents support
1 parent fca0626 commit b81bc0d

File tree

1 file changed

+82
-0
lines changed
  • boot/freeldr/freeldr/lib/fs

1 file changed

+82
-0
lines changed

boot/freeldr/freeldr/lib/fs/ext.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBu
4040
BOOLEAN ExtReadGroupDescriptor(PEXT_VOLUME_INFO Volume, ULONG Group, PEXT_GROUP_DESC GroupBuffer);
4141
ULONG* ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode);
4242
ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode);
43+
BOOLEAN ExtCopyBlockPointersByExtents(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, PEXT4_EXTENT_HEADER ExtentHeader);
4344
BOOLEAN ExtCopyIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock);
4445
BOOLEAN ExtCopyDoubleIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock);
4546
BOOLEAN ExtCopyTripleIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock);
@@ -1037,6 +1038,21 @@ ULONG* ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
10371038

10381039
RtlZeroMemory(BlockList, BlockCount * sizeof(ULONG));
10391040

1041+
// If the file is stored in extents, copy the block pointers by reading the
1042+
// extent entries.
1043+
if (Inode->Flags & EXT4_INODE_FLAG_EXTENTS)
1044+
{
1045+
CurrentBlockInList = 0;
1046+
1047+
if (!ExtCopyBlockPointersByExtents(Volume, BlockList, &CurrentBlockInList, BlockCount, &Inode->ExtentHeader))
1048+
{
1049+
FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
1050+
return NULL;
1051+
}
1052+
1053+
return BlockList;
1054+
}
1055+
10401056
// Copy the direct block pointers
10411057
for (CurrentBlockInList = CurrentBlock = 0;
10421058
CurrentBlockInList < BlockCount && CurrentBlock < sizeof(Inode->Blocks.DirectBlocks) / sizeof(*Inode->Blocks.DirectBlocks);
@@ -1090,6 +1106,72 @@ ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode)
10901106
}
10911107
}
10921108

1109+
BOOLEAN ExtCopyBlockPointersByExtents(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, PEXT4_EXTENT_HEADER ExtentHeader)
1110+
{
1111+
TRACE("ExtCopyBlockPointersByExtents() BlockCount = 0x%p\n", BlockCount);
1112+
1113+
if (ExtentHeader->Magic != EXT4_EXTENT_HEADER_MAGIC ||
1114+
ExtentHeader->Depth > EXT4_EXTENT_MAX_LEVEL)
1115+
return FALSE;
1116+
1117+
ULONG Level = ExtentHeader->Depth;
1118+
ULONG Entries = ExtentHeader->Entries;
1119+
1120+
TRACE("Level: %d\n", Level);
1121+
TRACE("Entries: %d\n", Entries);
1122+
1123+
// If the level is 0, we have a direct extent block mapping
1124+
if (!Level)
1125+
{
1126+
PEXT4_EXTENT Extent = (PVOID)&ExtentHeader[1];
1127+
1128+
while ((*CurrentBlockInList) < BlockCount && Entries--)
1129+
{
1130+
BOOLEAN SparseExtent = (Extent->Length > EXT4_EXTENT_MAX_LENGTH);
1131+
ULONG Length = SparseExtent ? (Extent->Length - EXT4_EXTENT_MAX_LENGTH) : Extent->Length;
1132+
ULONG CurrentBlock = SparseExtent ? 0 : Extent->Start;
1133+
1134+
// Copy the pointers to the block list
1135+
while ((*CurrentBlockInList) < BlockCount && Length--)
1136+
{
1137+
BlockList[(*CurrentBlockInList)++] = CurrentBlock;
1138+
1139+
if (!SparseExtent)
1140+
CurrentBlock++;
1141+
}
1142+
1143+
Extent++;
1144+
}
1145+
}
1146+
else
1147+
{
1148+
PEXT4_EXTENT_IDX Extent = (PVOID)&ExtentHeader[1];
1149+
1150+
PEXT4_EXTENT_HEADER BlockBuffer = FrLdrTempAlloc(Volume->BlockSizeInBytes, TAG_EXT_BUFFER);
1151+
if (!BlockBuffer)
1152+
{
1153+
return FALSE;
1154+
}
1155+
1156+
// Recursively copy the pointers to the block list
1157+
while ((*CurrentBlockInList) < BlockCount && Entries--)
1158+
{
1159+
if (!(ExtReadBlock(Volume, Extent->Leaf, BlockBuffer) &&
1160+
ExtCopyBlockPointersByExtents(Volume, BlockList, CurrentBlockInList, BlockCount, BlockBuffer)))
1161+
{
1162+
FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1163+
return FALSE;
1164+
}
1165+
1166+
Extent++;
1167+
}
1168+
1169+
FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1170+
}
1171+
1172+
return TRUE;
1173+
}
1174+
10931175
BOOLEAN ExtCopyIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock)
10941176
{
10951177
ULONG* BlockBuffer;

0 commit comments

Comments
 (0)