https://git.reactos.org/?p=reactos.git;a=commitdiff;h=56c8c8ab4f16633398356087ae9923d7b71bb467
commit 56c8c8ab4f16633398356087ae9923d7b71bb467 Author: Daniel Victor <ilauncherdevelo...@gmail.com> AuthorDate: Thu Feb 13 16:34:02 2025 -0300 Commit: Timo Kreuzer <timo.kreu...@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;