https://git.reactos.org/?p=reactos.git;a=commitdiff;h=56c8c8ab4f16633398356…
commit 56c8c8ab4f16633398356087ae9923d7b71bb467
Author: Daniel Victor <ilauncherdeveloper(a)gmail.com>
AuthorDate: Thu Feb 13 16:34:02 2025 -0300
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Thu Feb 20 19:28:41 2025 +0200
[FREELDR] Add Extents support
---
boot/freeldr/freeldr/lib/fs/ext.c | 82 +++++++++++++++++++++++++++++++++++++++
1 file changed, 82 insertions(+)
diff --git a/boot/freeldr/freeldr/lib/fs/ext.c b/boot/freeldr/freeldr/lib/fs/ext.c
index 6503bfca2f0..288d708a915 100644
--- a/boot/freeldr/freeldr/lib/fs/ext.c
+++ b/boot/freeldr/freeldr/lib/fs/ext.c
@@ -40,6 +40,7 @@ BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE
InodeBu
BOOLEAN ExtReadGroupDescriptor(PEXT_VOLUME_INFO Volume, ULONG Group, PEXT_GROUP_DESC
GroupBuffer);
ULONG* ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode);
ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode);
+BOOLEAN ExtCopyBlockPointersByExtents(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG*
CurrentBlockInList, ULONG BlockCount, PEXT4_EXTENT_HEADER ExtentHeader);
BOOLEAN ExtCopyIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG*
CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock);
BOOLEAN ExtCopyDoubleIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG* BlockList,
ULONG* CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock);
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)
RtlZeroMemory(BlockList, BlockCount * sizeof(ULONG));
+ // If the file is stored in extents, copy the block pointers by reading the
+ // extent entries.
+ if (Inode->Flags & EXT4_INODE_FLAG_EXTENTS)
+ {
+ CurrentBlockInList = 0;
+
+ if (!ExtCopyBlockPointersByExtents(Volume, BlockList, &CurrentBlockInList,
BlockCount, &Inode->ExtentHeader))
+ {
+ FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
+ return NULL;
+ }
+
+ return BlockList;
+ }
+
// Copy the direct block pointers
for (CurrentBlockInList = CurrentBlock = 0;
CurrentBlockInList < BlockCount && CurrentBlock <
sizeof(Inode->Blocks.DirectBlocks) / sizeof(*Inode->Blocks.DirectBlocks);
@@ -1090,6 +1106,72 @@ ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode)
}
}
+BOOLEAN ExtCopyBlockPointersByExtents(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG*
CurrentBlockInList, ULONG BlockCount, PEXT4_EXTENT_HEADER ExtentHeader)
+{
+ TRACE("ExtCopyBlockPointersByExtents() BlockCount = 0x%p\n", BlockCount);
+
+ if (ExtentHeader->Magic != EXT4_EXTENT_HEADER_MAGIC ||
+ ExtentHeader->Depth > EXT4_EXTENT_MAX_LEVEL)
+ return FALSE;
+
+ ULONG Level = ExtentHeader->Depth;
+ ULONG Entries = ExtentHeader->Entries;
+
+ TRACE("Level: %d\n", Level);
+ TRACE("Entries: %d\n", Entries);
+
+ // If the level is 0, we have a direct extent block mapping
+ if (!Level)
+ {
+ PEXT4_EXTENT Extent = (PVOID)&ExtentHeader[1];
+
+ while ((*CurrentBlockInList) < BlockCount && Entries--)
+ {
+ BOOLEAN SparseExtent = (Extent->Length > EXT4_EXTENT_MAX_LENGTH);
+ ULONG Length = SparseExtent ? (Extent->Length - EXT4_EXTENT_MAX_LENGTH) :
Extent->Length;
+ ULONG CurrentBlock = SparseExtent ? 0 : Extent->Start;
+
+ // Copy the pointers to the block list
+ while ((*CurrentBlockInList) < BlockCount && Length--)
+ {
+ BlockList[(*CurrentBlockInList)++] = CurrentBlock;
+
+ if (!SparseExtent)
+ CurrentBlock++;
+ }
+
+ Extent++;
+ }
+ }
+ else
+ {
+ PEXT4_EXTENT_IDX Extent = (PVOID)&ExtentHeader[1];
+
+ PEXT4_EXTENT_HEADER BlockBuffer = FrLdrTempAlloc(Volume->BlockSizeInBytes,
TAG_EXT_BUFFER);
+ if (!BlockBuffer)
+ {
+ return FALSE;
+ }
+
+ // Recursively copy the pointers to the block list
+ while ((*CurrentBlockInList) < BlockCount && Entries--)
+ {
+ if (!(ExtReadBlock(Volume, Extent->Leaf, BlockBuffer) &&
+ ExtCopyBlockPointersByExtents(Volume, BlockList, CurrentBlockInList,
BlockCount, BlockBuffer)))
+ {
+ FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
+ return FALSE;
+ }
+
+ Extent++;
+ }
+
+ FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
+ }
+
+ return TRUE;
+}
+
BOOLEAN ExtCopyIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG* BlockList, ULONG*
CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock)
{
ULONG* BlockBuffer;