You've already forked slimbootloader
mirror of
https://github.com/Dasharo/slimbootloader.git
synced 2026-03-06 15:26:20 -08:00
990e3e81e6
Convert the line endings stored for all text files in the repository to LF. The majority previously used DOS-style CRLF line endings. Add a .gitattributes file to enforce this and treat certain extensions as never being text files. Update PatchCheck.py to insist on LF line endings rather than CRLF. However, its other checks fail on this commit due to lots of pre-existing complaints that it only notices because the line endings have changed. Silicon/QemuSocPkg/FspBin/Patches/0001-Build-QEMU-FSP-2.0-binaries.patch needs to be treated as binary since it contains a mixture of line endings. This change has implications depending on the client platform you are using the repository from: * Windows The usual configuration for Git on Windows means that text files will be checked out to the work tree with DOS-style CRLF line endings. If that's not the case then you can configure Git to do so for the entire machine with: git config --global core.autocrlf true or for just the repository with: git config core.autocrlf true Line endings will be normalised to LF when they are committed to the repository. If you commit a text file with only LF line endings then it will be converted to CRLF line endings in your work tree. * Linux, MacOS and other Unices The usual configuration for Git on such platforms is to check files out of the repository with LF line endings. This is probably the right thing for you. In the unlikely even that you are using Git on Unix but editing or compiling on Windows for some reason then you may need to tweak your configuration to force the use of CRLF line endings as described above. * General For more information see https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings . Fixes: https://github.com/slimbootloader/slimbootloader/issues/1400 Signed-off-by: Mike Crowe <mac@mcrowe.com>
1210 lines
34 KiB
C
1210 lines
34 KiB
C
/** @file
|
|
|
|
Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
Copyright (c) 1997 Manuel Bouyer.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
-
|
|
Copyright (c) 1993
|
|
The Regents of the University of California. All rights reserved.
|
|
|
|
This code is derived from software contributed to Berkeley by
|
|
The Mach Operating System project at Carnegie-Mellon University.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
3. Neither the Name of the University nor the names of its contributors
|
|
may be used to endorse or promote products derived from this software
|
|
without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
SUCH DAMAGE.
|
|
|
|
|
|
Copyright (c) 1990, 1991 Carnegie Mellon University
|
|
All Rights Reserved.
|
|
|
|
Author: David Golub
|
|
|
|
Permission to use, copy, modify and distribute this software and its
|
|
documentation is hereby granted, provided that both the copyright
|
|
notice and this permission notice appear in all copies of the
|
|
software, derivative works or modified versions, and any portions
|
|
thereof, and that both notices appear in supporting documentation.
|
|
|
|
CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
|
CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
|
|
ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
|
|
|
Carnegie Mellon requests users of this software to return to
|
|
|
|
Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
|
School of Computer Science
|
|
Carnegie Mellon University
|
|
Pittsburgh PA 15213-3890
|
|
|
|
any improvements or extensions that they make and grant Carnegie the
|
|
rights to redistribute these changes.
|
|
|
|
Stand-alone FILE reading package for Ext2 FILE system.
|
|
**/
|
|
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/MediaAccessLib.h>
|
|
#include "Ext2Fs.h"
|
|
#include "LibsaFsStand.h"
|
|
|
|
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
|
|
|
|
#if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
|
|
#define LIBSA_NO_FS_SYMLINK
|
|
#endif
|
|
|
|
/**
|
|
Given an offset in a FILE, find the disk block number that
|
|
contains that block.
|
|
|
|
@param[in] File pointer to an Open file.
|
|
@param[in] FileBlock Block to find the file.
|
|
@param[out] DiskBlockPtr Pointer to the disk which contains block.
|
|
|
|
@retval 0 if success
|
|
@retval other if error.
|
|
**/
|
|
STATIC
|
|
RETURN_STATUS
|
|
BlockMap (
|
|
IN OPEN_FILE *File,
|
|
IN INDPTR FileBlock,
|
|
OUT INDPTR *DiskBlockPtr
|
|
);
|
|
|
|
/**
|
|
Search a directory for a Name and return its inode number.
|
|
|
|
@param[in] Name Name to compare with
|
|
@param[in] Length Length of the dir name
|
|
@param[in/out] File Pointer to file private data
|
|
@param[out] INumPtr pointer to Inode number.
|
|
|
|
@retval 0 if success
|
|
@retval other if error.
|
|
**/
|
|
STATIC
|
|
RETURN_STATUS
|
|
SearchDirectory (
|
|
IN CHAR8 *Name,
|
|
IN INT32 Length,
|
|
IN OUT OPEN_FILE *File,
|
|
OUT INODE32 *INumPtr
|
|
);
|
|
|
|
/**
|
|
Gives the info of device block config.
|
|
|
|
@param[in] DevData Device privete data.
|
|
@param[in] ReadWrite Read or Write
|
|
@param[in] BlockNum Block number to start
|
|
@param[in] Size Size to read block.
|
|
@param[out] Buf Buffer to read the block data.
|
|
@param[out] RSize Actual read size
|
|
|
|
@retval 0 if success
|
|
@retval other if error.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
BDevStrategy (
|
|
IN VOID *DevData,
|
|
IN INT32 ReadWrite,
|
|
IN DADDRESS BlockNum,
|
|
IN UINT32 Size,
|
|
OUT VOID *Buf,
|
|
OUT UINT32 *RSize
|
|
)
|
|
{
|
|
RETURN_STATUS Status;
|
|
PEI_EXT_PRIVATE_DATA *PrivateData;
|
|
UINT64 Startblockno;
|
|
|
|
PrivateData = DevData;
|
|
|
|
if (ReadWrite != F_READ && ReadWrite != F_WRITE) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
if ((Size % PrivateData->BlockSize) != 0) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Startblockno = BlockNum + PrivateData->StartBlock;
|
|
if (ReadWrite == F_READ) {
|
|
Status = MediaReadBlocks (PrivateData->PhysicalDevNo, (UINT32)Startblockno, Size, Buf);
|
|
if (RETURN_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
*RSize = Size;
|
|
return RETURN_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Read a new inode into a FILE structure.
|
|
|
|
@param[in] INumber inode number
|
|
@param[in/out] File pointer to open file struct.
|
|
|
|
@retval 0 if success
|
|
@retval other if error.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
ReadInode (
|
|
IN INODE32 INumber,
|
|
IN OPEN_FILE *File
|
|
)
|
|
{
|
|
FILE *Fp;
|
|
M_EXT2FS *FileSystem;
|
|
CHAR8 *Buf;
|
|
UINT32 RSize;
|
|
RETURN_STATUS Status;
|
|
DADDRESS InodeSector;
|
|
EXT2GD *Ext2FsGrpDes;
|
|
EXTFS_DINODE *DInodePtr;
|
|
|
|
Fp = (FILE *)File->FileSystemSpecificData;
|
|
FileSystem = Fp->SuperBlockPtr;
|
|
|
|
Ext2FsGrpDes = FileSystem->Ext2FsGrpDes;
|
|
Ext2FsGrpDes = (EXT2GD*)((UINTN)Ext2FsGrpDes + (INOTOCG(FileSystem, INumber) * FileSystem->Ext2FsGDSize));
|
|
|
|
InodeSector = (DADDRESS) (Ext2FsGrpDes->Ext2BGDInodeTables + DivU64x32 (ModU64x32 ((INumber - 1), FileSystem->Ext2Fs.Ext2FsINodesPerGroup), FileSystem->Ext2FsInodesPerBlock));
|
|
|
|
if (FileSystem->Ext2FsGDSize > 32) {
|
|
if (Ext2FsGrpDes->Ext2BGDInodeTablesHi !=0) {
|
|
InodeSector |= LShiftU64 ((UINT64) (Ext2FsGrpDes->Ext2BGDInodeTablesHi), 32);
|
|
}
|
|
}
|
|
InodeSector = FSBTODB (FileSystem, InodeSector);
|
|
|
|
//
|
|
// Read inode and save it.
|
|
//
|
|
Buf = Fp->Buffer;
|
|
Status = DEV_STRATEGY (File->DevPtr) (File->FileDevData, F_READ,
|
|
InodeSector, FileSystem->Ext2FsBlockSize, Buf, &RSize);
|
|
if (RETURN_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (RSize != (UINT32)FileSystem->Ext2FsBlockSize) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
DInodePtr = (EXTFS_DINODE *) (Buf +
|
|
EXT2_DINODE_SIZE (FileSystem) * INODETOFSBO (FileSystem, INumber));
|
|
E2FSILOAD (DInodePtr, &Fp->DiskInode);
|
|
|
|
//
|
|
// Clear out the Old buffers
|
|
//
|
|
Fp->InodeCacheBlock = ~0;
|
|
Fp->BufferBlockNum = -1;
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Given an offset in a FILE, find the disk block number that
|
|
contains that block.
|
|
|
|
@param[in] File pointer to an Open file.
|
|
@param[in] FileBlock Block to find the file.
|
|
@param[out] DiskBlockPtr Pointer to the disk which contains block.
|
|
|
|
@retval 0 if success
|
|
@retval other if error.
|
|
**/
|
|
STATIC
|
|
RETURN_STATUS
|
|
BlockMap (
|
|
IN OPEN_FILE *File,
|
|
IN INDPTR FileBlock,
|
|
OUT INDPTR *DiskBlockPtr
|
|
)
|
|
{
|
|
FILE *Fp;
|
|
M_EXT2FS *FileSystem;
|
|
UINT32 Level;
|
|
INDPTR IndCache;
|
|
INDPTR IndBlockNum;
|
|
UINT32 RSize;
|
|
INDPTR *Buf;
|
|
UINT32 Index;
|
|
UINT64 NextLevelNode;
|
|
EXT4_EXTENT_TABLE *Etable;
|
|
EXT4_EXTENT_INDEX *ExtIndex;
|
|
EXT4_EXTENT *Extent;
|
|
RETURN_STATUS Status;
|
|
|
|
Fp = (FILE *)File->FileSystemSpecificData;
|
|
FileSystem = Fp->SuperBlockPtr;
|
|
Buf = (VOID *)Fp->Buffer;
|
|
|
|
if ((Fp->DiskInode.Ext2DInodeStatusFlags & EXT4_EXTENTS) != 0) {
|
|
Etable = (EXT4_EXTENT_TABLE*) &(Fp->DiskInode.Ext2DInodeBlocks);
|
|
if (Etable->Eheader.EhMagic != EXT4_EXTENT_HEADER_MAGIC) {
|
|
DEBUG ((DEBUG_ERROR, "EXT4 extent header magic mismatch 0x%X!\n", Etable->Eheader.EhMagic));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
while (Etable->Eheader.EhDepth > 0) {
|
|
ExtIndex = NULL;
|
|
for (Index=1; Index < Etable->Eheader.EhEntries; Index++) {
|
|
ExtIndex = &(Etable->Enodes.Eindex[Index]);
|
|
if (((UINT32) FileBlock) < ExtIndex->EiBlk) {
|
|
ExtIndex = &(Etable->Enodes.Eindex[Index-1]);
|
|
break;
|
|
}
|
|
ExtIndex = NULL;
|
|
}
|
|
|
|
if (ExtIndex != NULL) {
|
|
//
|
|
// TODO: Need to support 48-bit block device addressing.
|
|
// Throw an ASSERT if upper 16-bits are non-zero.
|
|
//
|
|
ASSERT (ExtIndex->EiLeafHi == 0);
|
|
NextLevelNode = ExtIndex->EiLeafLo; //LShiftU64((UINT64)ExtIndex->EiLeafHi, 32) | ExtIndex->EiLeafLo;
|
|
|
|
//
|
|
// We need to read the next level node of the extent tree since the data was not in the current level.
|
|
//
|
|
Status = DEV_STRATEGY (File->DevPtr) (File->FileDevData, F_READ,
|
|
FSBTODB (Fp->SuperBlockPtr, (DADDRESS) NextLevelNode), FileSystem->Ext2FsBlockSize,
|
|
Buf, &RSize);
|
|
if (RETURN_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (RSize != (UINT32)FileSystem->Ext2FsBlockSize) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
Etable = (EXT4_EXTENT_TABLE*) Buf;
|
|
if (Etable->Eheader.EhMagic != EXT4_EXTENT_HEADER_MAGIC) {
|
|
DEBUG ((DEBUG_ERROR, "EXT4 extent header magic mismatch 0x%X!\n", Etable->Eheader.EhMagic));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_ERROR, "Could not find FileBlock #%d in the index extent data!\n", FileBlock));
|
|
return EFI_NO_MAPPING;
|
|
}
|
|
}
|
|
|
|
Extent = NULL;
|
|
for (Index=0; Index < Etable->Eheader.EhEntries; Index++) {
|
|
Extent = &(Etable->Enodes.Extent[Index]);
|
|
if ((((UINT32) FileBlock) >= Extent->Eblk) && (((UINT32) FileBlock) < (Extent->Eblk + Extent->Elen))) {
|
|
break;
|
|
}
|
|
Extent = NULL;
|
|
}
|
|
|
|
if (Extent != NULL) {
|
|
//
|
|
// TODO: Need to support 48-bit block device addressing
|
|
// Throw an ASSERT if upper 16-bits are non-zero.
|
|
//
|
|
ASSERT (Extent->EstartHi == 0);
|
|
*DiskBlockPtr = Extent->EstartLo + (FileBlock - Extent->Eblk); // (LShiftU64((UINT64)Extent->EiLeafHi, 32) | Extent->EstartLo) + (FileBlock - Extent->Eblk);
|
|
} else {
|
|
*DiskBlockPtr = 0;
|
|
}
|
|
} else {
|
|
if (FileBlock < NDADDR) {
|
|
//
|
|
// Direct block.
|
|
//
|
|
*DiskBlockPtr = Fp->DiskInode.Ext2DInodeBlocks[FileBlock];
|
|
return 0;
|
|
}
|
|
|
|
FileBlock -= NDADDR;
|
|
|
|
IndCache = FileBlock >> LN2_IND_CACHE_SZ;
|
|
if (IndCache == Fp->InodeCacheBlock) {
|
|
*DiskBlockPtr =
|
|
Fp->InodeCache[FileBlock & IND_CACHE_MASK];
|
|
return 0;
|
|
}
|
|
|
|
for (Level = 0;;) {
|
|
Level += Fp->NiShift;
|
|
if (FileBlock < (INDPTR)1 << Level) {
|
|
break;
|
|
}
|
|
if (Level > NIADDR * Fp->NiShift)
|
|
//
|
|
// Block number too high
|
|
//
|
|
{
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
FileBlock -= (INDPTR)1 << Level;
|
|
}
|
|
|
|
IndBlockNum =
|
|
Fp->DiskInode.Ext2DInodeBlocks[NDADDR + (Level / Fp->NiShift - 1)];
|
|
|
|
while (1) {
|
|
Level -= Fp->NiShift;
|
|
if (IndBlockNum == 0) {
|
|
*DiskBlockPtr = 0; // missing
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// If we were feeling brave, we could work out the number
|
|
// of the disk sector and read a single disk sector instead
|
|
// of a filesystem block.
|
|
// However we don't do this very often anyway...
|
|
//
|
|
Status = DEV_STRATEGY (File->DevPtr) (File->FileDevData, F_READ,
|
|
FSBTODB (Fp->SuperBlockPtr, IndBlockNum), FileSystem->Ext2FsBlockSize,
|
|
Buf, &RSize);
|
|
if (RETURN_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (RSize != (UINT32)FileSystem->Ext2FsBlockSize) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
IndBlockNum = Buf[FileBlock >> Level];
|
|
if (Level == 0) {
|
|
break;
|
|
}
|
|
FileBlock &= (1 << Level) - 1;
|
|
}
|
|
//
|
|
// Save the part of the block that contains this sector
|
|
//
|
|
CopyMem (Fp->InodeCache, &Buf[FileBlock & ~IND_CACHE_MASK],
|
|
IND_CACHE_SZ * sizeof Fp->InodeCache[0]);
|
|
Fp->InodeCacheBlock = IndCache;
|
|
|
|
*DiskBlockPtr = IndBlockNum;
|
|
}
|
|
|
|
return RETURN_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Read a portion of a FILE into an internal buffer.
|
|
|
|
Return the location in the buffer and the amount in the buffer.
|
|
|
|
@param[in] File Pointer to the open file.
|
|
@param[out] BufferPtr buffer corresponding to offset
|
|
@param[out] SizePtr Size of remainder of buffer.
|
|
|
|
@retval 0 if success
|
|
@retval other if error.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
BufReadFile (
|
|
IN OPEN_FILE *File,
|
|
OUT CHAR8 **BufferPtr,
|
|
OUT UINT32 *SizePtr
|
|
)
|
|
{
|
|
FILE *Fp;
|
|
M_EXT2FS *FileSystem;
|
|
INT32 Off;
|
|
INDPTR FileBlock;
|
|
INDPTR DiskBlock;
|
|
UINT32 BlockSize;
|
|
RETURN_STATUS Rc;
|
|
|
|
Fp = (FILE *)File->FileSystemSpecificData;
|
|
FileSystem = Fp->SuperBlockPtr;
|
|
DiskBlock = 0;
|
|
|
|
Off = BLOCKOFFSET (FileSystem, Fp->SeekPtr);
|
|
FileBlock = LBLKNO (FileSystem, Fp->SeekPtr);
|
|
BlockSize = FileSystem->Ext2FsBlockSize; // no fragment
|
|
|
|
if (FileBlock != Fp->BufferBlockNum) {
|
|
Rc = BlockMap (File, FileBlock, &DiskBlock);
|
|
if (Rc != 0) {
|
|
return Rc;
|
|
}
|
|
|
|
if (DiskBlock == 0) {
|
|
SetMem32 (Fp->Buffer, BlockSize, 0);
|
|
Fp->BufferSize = BlockSize;
|
|
} else {
|
|
|
|
Rc = DEV_STRATEGY (File->DevPtr) (File->FileDevData, F_READ,
|
|
FSBTODB (FileSystem, DiskBlock),
|
|
BlockSize, Fp->Buffer, &Fp->BufferSize);
|
|
if (Rc != 0) {
|
|
return Rc;
|
|
}
|
|
}
|
|
|
|
Fp->BufferBlockNum = FileBlock;
|
|
}
|
|
|
|
//
|
|
// Return address of byte in buffer corresponding to
|
|
// offset, and Size of remainder of buffer after that
|
|
// byte.
|
|
//
|
|
*BufferPtr = Fp->Buffer + Off;
|
|
*SizePtr = BlockSize - Off;
|
|
|
|
//
|
|
// But truncate buffer at end of FILE.
|
|
//
|
|
// XXX should handle LARGEFILE
|
|
//
|
|
if (*SizePtr > Fp->DiskInode.Ext2DInodeSize - Fp->SeekPtr) {
|
|
*SizePtr = Fp->DiskInode.Ext2DInodeSize - Fp->SeekPtr;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Search a directory for a Name and return its inode number.
|
|
|
|
@param[in] Name Name to compare with
|
|
@param[in] Length Length of the dir name
|
|
@param[in/out] File Pointer to file private data
|
|
@param[out] INumPtr pointer to Inode number.
|
|
|
|
@retval 0 if success
|
|
@retval other if error.
|
|
**/
|
|
STATIC
|
|
RETURN_STATUS
|
|
SearchDirectory (
|
|
IN CHAR8 *Name,
|
|
IN INT32 Length,
|
|
IN OUT OPEN_FILE *File,
|
|
OUT INODE32 *INumPtr
|
|
)
|
|
{
|
|
FILE *Fp;
|
|
EXT2FS_DIRECT *Dp;
|
|
EXT2FS_DIRECT *EdPtr;
|
|
CHAR8 *Buf;
|
|
UINT32 BufSize;
|
|
INT32 NameLen;
|
|
RETURN_STATUS Status;
|
|
|
|
Fp = (FILE *)File->FileSystemSpecificData;
|
|
|
|
Fp->SeekPtr = 0;
|
|
//
|
|
// XXX should handle LARGEFILE
|
|
//
|
|
while (Fp->SeekPtr < (OFFSET)Fp->DiskInode.Ext2DInodeSize) {
|
|
Status = BufReadFile (File, &Buf, &BufSize);
|
|
if (RETURN_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Dp = (EXT2FS_DIRECT *)Buf;
|
|
EdPtr = (EXT2FS_DIRECT *) (Buf + BufSize);
|
|
for (; Dp < EdPtr;
|
|
Dp = (VOID *) ((CHAR8 *)Dp + Dp->Ext2DirectRecLen)) {
|
|
if (Dp->Ext2DirectRecLen <= 0) {
|
|
break;
|
|
}
|
|
if (Dp->Ext2DirectInodeNumber == (INODE32)0) {
|
|
continue;
|
|
}
|
|
NameLen = Dp->Ext2DirectNameLen;
|
|
if (NameLen == Length &&
|
|
!CompareMem (Name, Dp->Ext2DirectName, Length)) {
|
|
//
|
|
// found entry
|
|
//
|
|
*INumPtr = Dp->Ext2DirectInodeNumber;
|
|
File->FileNamePtr = Name;
|
|
return 0;
|
|
}
|
|
}
|
|
Fp->SeekPtr += BufSize;
|
|
}
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Validate EXT2 Superblock
|
|
|
|
@param[in] FsHandle EXT file system handle.
|
|
@param[in] File File for which super block needs to be read.
|
|
@param[out] RExt2Fs EXT2FS meta data to retreive.
|
|
|
|
@retval 0 if superblock validation is success
|
|
@retval other if error.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
Ext2SbValidate (
|
|
IN CONST EFI_HANDLE FsHandle,
|
|
IN CONST OPEN_FILE *File OPTIONAL,
|
|
OUT EXT2FS *RExt2Fs OPTIONAL
|
|
)
|
|
{
|
|
PEI_EXT_PRIVATE_DATA *PrivateData;
|
|
UINT8 *Buffer;
|
|
EXT2FS *Ext2Fs;
|
|
UINT32 BufSize;
|
|
RETURN_STATUS Rc;
|
|
UINT32 SbOffset;
|
|
|
|
Rc = 0;
|
|
Buffer = NULL;
|
|
|
|
if (FsHandle == NULL) {
|
|
Rc = RETURN_INVALID_PARAMETER;
|
|
goto Exit;
|
|
}
|
|
|
|
PrivateData = (PEI_EXT_PRIVATE_DATA *)FsHandle;
|
|
|
|
Buffer = AllocatePool ((PrivateData->BlockSize > SBSIZE) ? PrivateData->BlockSize : SBSIZE);
|
|
if (Buffer == NULL) {
|
|
Rc = EFI_OUT_OF_RESOURCES;
|
|
goto Exit;
|
|
}
|
|
|
|
if (File == NULL) {
|
|
Rc = BDevStrategy (PrivateData, F_READ,
|
|
SBOFF / PrivateData->BlockSize, PrivateData->BlockSize, Buffer, &BufSize);
|
|
} else {
|
|
Rc = DEV_STRATEGY (File->DevPtr) (PrivateData, F_READ,
|
|
SBOFF / PrivateData->BlockSize, PrivateData->BlockSize,
|
|
Buffer, &BufSize);
|
|
}
|
|
|
|
if (Rc != 0) {
|
|
goto Exit;
|
|
}
|
|
|
|
SbOffset = (SBOFF < PrivateData->BlockSize) ? SBOFF : 0;
|
|
Ext2Fs = (EXT2FS *)(&Buffer[SbOffset]);
|
|
if (Ext2Fs->Ext2FsMagic != E2FS_MAGIC) {
|
|
Rc = EFI_UNSUPPORTED;
|
|
goto Exit;
|
|
}
|
|
|
|
if (Ext2Fs->Ext2FsRev > E2FS_REV1 ||
|
|
(Ext2Fs->Ext2FsRev == E2FS_REV1 &&
|
|
(Ext2Fs->Ext2FsFirstInode != EXT2_FIRSTINO ||
|
|
(Ext2Fs->Ext2FsInodeSize != 128 && Ext2Fs->Ext2FsInodeSize != 256) ||
|
|
Ext2Fs->Ext2FsFeaturesIncompat & ~EXT2F_INCOMPAT_SUPP))) {
|
|
Rc = EFI_UNSUPPORTED;
|
|
goto Exit;
|
|
}
|
|
|
|
if (Ext2Fs->Ext2FsRev == E2FS_REV0) {
|
|
Ext2Fs->Ext2FsFirstInode = 11;
|
|
Ext2Fs->Ext2FsInodeSize = 128;
|
|
}
|
|
|
|
if (RExt2Fs != NULL) {
|
|
E2FS_SBLOAD ((VOID *)Ext2Fs, RExt2Fs);
|
|
}
|
|
|
|
Exit:
|
|
if (Buffer != NULL) {
|
|
FreePool (Buffer);
|
|
}
|
|
|
|
return Rc;
|
|
}
|
|
|
|
/**
|
|
Read Superblock of the file.
|
|
|
|
@param[in] File File for which super block needs to be read.
|
|
@param[in/out] FileSystem Fs on which super block is computed.
|
|
|
|
@retval 0 if superblock compute is success
|
|
@retval other if error.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
ReadSBlock (
|
|
IN OPEN_FILE *File,
|
|
IN OUT M_EXT2FS *FileSystem
|
|
)
|
|
{
|
|
PEI_EXT_PRIVATE_DATA *PrivateData;
|
|
RETURN_STATUS Rc;
|
|
|
|
Rc = 0;
|
|
|
|
PrivateData = (PEI_EXT_PRIVATE_DATA*) File->FileDevData;
|
|
|
|
Rc = Ext2SbValidate ((EFI_HANDLE)PrivateData, File, &FileSystem->Ext2Fs);
|
|
if (RETURN_ERROR (Rc)) {
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// compute in-memory m_ext2fs values
|
|
//
|
|
FileSystem->Ext2FsNumCylinder =
|
|
HOWMANY (FileSystem->Ext2Fs.Ext2FsBlockCount - FileSystem->Ext2Fs.Ext2FsFirstDataBlock,
|
|
FileSystem->Ext2Fs.Ext2FsBlocksPerGroup);
|
|
|
|
FileSystem->Ext2FsFsbtobd = (INT32)(FileSystem->Ext2Fs.Ext2FsLogBlockSize + 10) - (INT32)HighBitSet32 (PrivateData->BlockSize);
|
|
FileSystem->Ext2FsBlockSize = MINBSIZE << FileSystem->Ext2Fs.Ext2FsLogBlockSize;
|
|
FileSystem->Ext2FsLogicalBlock = LOG_MINBSIZE + FileSystem->Ext2Fs.Ext2FsLogBlockSize;
|
|
FileSystem->Ext2FsQuadBlockOffset = FileSystem->Ext2FsBlockSize - 1;
|
|
FileSystem->Ext2FsBlockOffset = (UINT32)~FileSystem->Ext2FsQuadBlockOffset;
|
|
FileSystem->Ext2FsGDSize = 32;
|
|
if (FileSystem->Ext2Fs.Ext2FsFeaturesIncompat & EXT2F_INCOMPAT_64BIT) {
|
|
FileSystem->Ext2FsGDSize = FileSystem->Ext2Fs.Ext2FsGDSize;
|
|
}
|
|
FileSystem->Ext2FsNumGrpDesBlock =
|
|
HOWMANY (FileSystem->Ext2FsNumCylinder, FileSystem->Ext2FsBlockSize / FileSystem->Ext2FsGDSize);
|
|
FileSystem->Ext2FsInodesPerBlock = FileSystem->Ext2FsBlockSize / FileSystem->Ext2Fs.Ext2FsInodeSize;
|
|
FileSystem->Ext2FsInodesTablePerGrp = FileSystem->Ext2Fs.Ext2FsINodesPerGroup / FileSystem->Ext2FsInodesPerBlock;
|
|
|
|
Exit:
|
|
return Rc;
|
|
}
|
|
|
|
/**
|
|
Read group descriptor of the file.
|
|
|
|
@param[in/out] File File for which group descriptor needs to be read.
|
|
@param[in] FileSystem Fs on which super block is computed.
|
|
|
|
@retval 0 if Group descriptor read is success
|
|
@retval other if error.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
ReadGDBlock (
|
|
IN OUT OPEN_FILE *File,
|
|
IN M_EXT2FS *FileSystem
|
|
)
|
|
{
|
|
FILE *Fp;
|
|
UINT32 RSize;
|
|
UINT32 gdpb;
|
|
INT32 Index;
|
|
RETURN_STATUS Status;
|
|
|
|
Fp = (FILE *)File->FileSystemSpecificData;
|
|
|
|
gdpb = FileSystem->Ext2FsBlockSize / FileSystem->Ext2FsGDSize;
|
|
|
|
for (Index = 0; Index < FileSystem->Ext2FsNumGrpDesBlock; Index++) {
|
|
Status = DEV_STRATEGY (File->DevPtr) (File->FileDevData, F_READ,
|
|
FSBTODB (FileSystem, FileSystem->Ext2Fs.Ext2FsFirstDataBlock +
|
|
1 /* superblock */ + Index),
|
|
FileSystem->Ext2FsBlockSize, Fp->Buffer, &RSize);
|
|
if (RETURN_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
if (RSize != (UINT32)FileSystem->Ext2FsBlockSize) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
E2FS_CGLOAD ((EXT2GD *)Fp->Buffer,
|
|
&FileSystem->Ext2FsGrpDes[Index * gdpb],
|
|
(Index == (FileSystem->Ext2FsNumGrpDesBlock - 1)) ?
|
|
(FileSystem->Ext2FsNumCylinder - gdpb * Index) * FileSystem->Ext2FsGDSize :
|
|
FileSystem->Ext2FsBlockSize);
|
|
}
|
|
|
|
return RETURN_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Open struct file.
|
|
|
|
@param[in] Path Path to locate the file
|
|
@param[in/out] File The struct having the device and file info
|
|
|
|
@retval RETURN_SUCCESS if file open is success
|
|
@retval other if error.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
Ext2fsOpen (
|
|
IN CHAR8 *Path,
|
|
IN OUT OPEN_FILE *File
|
|
)
|
|
{
|
|
#ifndef LIBSA_FS_SINGLECOMPONENT
|
|
CHAR8 *Cp;
|
|
CHAR8 *Ncp;
|
|
INT32 Component;
|
|
#endif
|
|
INODE32 INumber;
|
|
FILE *Fp;
|
|
M_EXT2FS *FileSystem;
|
|
RETURN_STATUS Status;
|
|
#ifndef LIBSA_NO_FS_SYMLINK
|
|
INODE32 ParentInumber;
|
|
INT32 Nlinks;
|
|
CHAR8 NameBuf[MAXPATHLEN+1];
|
|
CHAR8 *Buf;
|
|
|
|
Nlinks = 0;
|
|
#endif
|
|
|
|
INDPTR mult;
|
|
INT32 Length2;
|
|
|
|
//
|
|
// allocate struct file system specific data structure
|
|
//
|
|
Fp = AllocatePool (sizeof (FILE));
|
|
if (Fp == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto out;
|
|
}
|
|
|
|
SetMem32 (Fp, sizeof (FILE), 0 );
|
|
File->FileSystemSpecificData = (VOID *)Fp;
|
|
//
|
|
// allocate space and read super block
|
|
//
|
|
FileSystem = AllocatePool (sizeof (*FileSystem));
|
|
if (FileSystem == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto out;
|
|
}
|
|
|
|
SetMem32 (FileSystem, sizeof (*FileSystem), 0);
|
|
Fp->SuperBlockPtr = FileSystem;
|
|
|
|
Status = ReadSBlock (File, FileSystem);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
|
|
#ifdef EXT2FS_DEBUG
|
|
DumpSBlock (FileSystem);
|
|
#endif
|
|
//
|
|
// alloc a block sized buffer used for all FileSystem transfers
|
|
//
|
|
Fp->Buffer = AllocatePool (FileSystem->Ext2FsBlockSize);
|
|
//
|
|
// read group descriptor blocks
|
|
//
|
|
FileSystem->Ext2FsGrpDes = AllocatePool (FileSystem->Ext2FsGDSize * FileSystem->Ext2FsNumCylinder);
|
|
Status = ReadGDBlock (File, FileSystem);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
|
|
#ifdef EXT2FS_DEBUG
|
|
DumpGroupDesBlock (FileSystem);
|
|
#endif
|
|
//
|
|
// Calculate indirect block levels.
|
|
//
|
|
//
|
|
// We note that the number of indirect blocks is always
|
|
// a power of 2. This lets us use shifts and masks instead
|
|
// of divide and remainder and avoinds pulling in the
|
|
// 64bit division routine into the boot code.
|
|
//
|
|
mult = NINDIR (FileSystem);
|
|
for (Length2 = 0; mult != 1; Length2++) {
|
|
mult >>= 1;
|
|
}
|
|
|
|
Fp->NiShift = Length2;
|
|
|
|
INumber = EXT2_ROOTINO;
|
|
Status = ReadInode (INumber, File);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
|
|
#ifndef LIBSA_FS_SINGLECOMPONENT
|
|
Cp = Path;
|
|
while (*Cp != '\0') {
|
|
//
|
|
// Remove extra separators
|
|
//
|
|
while (*Cp == '/') {
|
|
Cp++;
|
|
}
|
|
if (*Cp == '\0') {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Check that current node is a directory.
|
|
//
|
|
if ((Fp->DiskInode.Ext2DInodeMode & EXT2_IFMT) != EXT2_IFDIR) {
|
|
Status = EFI_LOAD_ERROR;
|
|
goto out;
|
|
}
|
|
|
|
//
|
|
// Get next component of Path Name.
|
|
//
|
|
Ncp = Cp;
|
|
while ((Component = *Cp) != '\0' && Component != '/') {
|
|
Cp++;
|
|
}
|
|
|
|
//
|
|
// Look up component in current directory.
|
|
// Save directory INumber in case we find a
|
|
// symbolic link.
|
|
//
|
|
#ifndef LIBSA_NO_FS_SYMLINK
|
|
ParentInumber = INumber;
|
|
#endif
|
|
Status = SearchDirectory (Ncp, (INT32)(Cp - Ncp), File, &INumber);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
|
|
//
|
|
// Open next component.
|
|
//
|
|
Status = ReadInode (INumber, File);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
|
|
#ifndef LIBSA_NO_FS_SYMLINK
|
|
//
|
|
// Check for symbolic link.
|
|
//
|
|
if ((Fp->DiskInode.Ext2DInodeMode & EXT2_IFMT) == EXT2_IFLNK) {
|
|
//
|
|
// XXX should handle LARGEFILE
|
|
//
|
|
UINTN LinkLength;
|
|
UINTN Len;
|
|
|
|
LinkLength = Fp->DiskInode.Ext2DInodeSize;
|
|
|
|
Len = AsciiStrLen (Cp);
|
|
|
|
if (((LinkLength + Len) > MAXPATHLEN) ||
|
|
((++Nlinks) > MAXSYMLINKS)) {
|
|
Status = RETURN_LOAD_ERROR;
|
|
goto out;
|
|
}
|
|
|
|
CopyMem (&NameBuf[LinkLength], Cp, Len + 1);
|
|
|
|
if (LinkLength < EXT2_MAXSYMLINKLEN) {
|
|
CopyMem (NameBuf, Fp->DiskInode.Ext2DInodeBlocks, LinkLength);
|
|
} else {
|
|
//
|
|
// Read FILE for symbolic link
|
|
//
|
|
UINT32 BufSize;
|
|
INDPTR DiskBlock;
|
|
|
|
Buf = Fp->Buffer;
|
|
Status = BlockMap (File, (INDPTR)0, &DiskBlock);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
|
|
Status = DEV_STRATEGY (File->DevPtr) (File->FileDevData,
|
|
F_READ, FSBTODB (FileSystem, DiskBlock),
|
|
FileSystem->Ext2FsBlockSize, Buf, &BufSize);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
|
|
CopyMem (NameBuf, Buf, LinkLength);
|
|
}
|
|
|
|
//
|
|
// If relative pathname, restart at parent directory.
|
|
// If absolute pathname, restart at root.
|
|
//
|
|
Cp = NameBuf;
|
|
if (*Cp != '/') {
|
|
INumber = ParentInumber;
|
|
} else {
|
|
INumber = (INODE32)EXT2_ROOTINO;
|
|
}
|
|
|
|
Status = ReadInode (INumber, File);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
}
|
|
#endif // !LIBSA_NO_FS_SYMLINK
|
|
}
|
|
|
|
//
|
|
// Found terminal component.
|
|
//
|
|
Status = RETURN_SUCCESS;
|
|
|
|
#else // !LIBSA_FS_SINGLECOMPONENT
|
|
//
|
|
// look up component in the current (root) directory
|
|
//
|
|
Status = SearchDirectory (Path, AsciiStrLen (Path), File, &INumber);
|
|
if (RETURN_ERROR (Status)) {
|
|
goto out;
|
|
}
|
|
//
|
|
// open it
|
|
//
|
|
Status = ReadInode (INumber, File);
|
|
|
|
#endif // !LIBSA_FS_SINGLECOMPONENT
|
|
|
|
Fp->SeekPtr = 0; // reset seek pointer
|
|
|
|
out:
|
|
if (RETURN_ERROR (Status)) {
|
|
Ext2fsClose (File);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Close the opened file.
|
|
|
|
@param[in/out] File File to be closed.
|
|
|
|
@retval RETURN_SUCCESS regardless of success/fail condition
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
Ext2fsClose (
|
|
IN OUT OPEN_FILE *File
|
|
)
|
|
{
|
|
FILE *Fp;
|
|
|
|
Fp = (FILE *)File->FileSystemSpecificData;
|
|
|
|
File->FileSystemSpecificData = NULL;
|
|
if (Fp == NULL) {
|
|
return RETURN_SUCCESS;
|
|
}
|
|
|
|
if (Fp->SuperBlockPtr->Ext2FsGrpDes) {
|
|
FreePool (Fp->SuperBlockPtr->Ext2FsGrpDes);
|
|
}
|
|
if (Fp->Buffer) {
|
|
FreePool (Fp->Buffer);
|
|
}
|
|
FreePool (Fp->SuperBlockPtr);
|
|
FreePool (Fp);
|
|
return RETURN_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Gets the size of the file from descriptor.
|
|
|
|
@param[in] File File to be closed.
|
|
|
|
@retval size of the file from descriptor.
|
|
**/
|
|
UINT32
|
|
EFIAPI
|
|
Ext2fsFileSize (
|
|
IN OPEN_FILE *File
|
|
)
|
|
{
|
|
FILE *Fp;
|
|
Fp = (FILE *)File->FileSystemSpecificData;
|
|
return (UINT32)Fp->DiskInode.Ext2DInodeSize;
|
|
}
|
|
|
|
/**
|
|
Copy a portion of a FILE into a memory.
|
|
Cross block boundaries when necessary
|
|
|
|
@param[in/out] File File handle to be read
|
|
@param[in] Start Start address of read buffer
|
|
@param[in] Size Size to be read
|
|
@param[out] ResId Actual read size
|
|
|
|
@retval RETURN_SUCCESS if file read is success
|
|
@retval other if error.
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
Ext2fsRead (
|
|
IN OUT OPEN_FILE *File,
|
|
IN VOID *Start,
|
|
IN UINT32 Size,
|
|
OUT UINT32 *ResId
|
|
)
|
|
{
|
|
FILE *Fp;
|
|
UINT32 Csize;
|
|
CHAR8 *Buf;
|
|
UINT32 BufSize;
|
|
CHAR8 *Address;
|
|
RETURN_STATUS Status;
|
|
|
|
Fp = (FILE *)File->FileSystemSpecificData;
|
|
Status = RETURN_SUCCESS;
|
|
Address = Start;
|
|
|
|
while (Size != 0) {
|
|
//
|
|
// XXX should handle LARGEFILE
|
|
//
|
|
if (Fp->SeekPtr >= (OFFSET)Fp->DiskInode.Ext2DInodeSize) {
|
|
break;
|
|
}
|
|
|
|
Status = BufReadFile (File, &Buf, &BufSize);
|
|
if (RETURN_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
Csize = Size;
|
|
if (Csize > BufSize) {
|
|
Csize = BufSize;
|
|
}
|
|
|
|
CopyMem (Address, Buf, Csize);
|
|
|
|
Fp->SeekPtr += Csize;
|
|
Address += Csize;
|
|
Size -= Csize;
|
|
}
|
|
if (ResId != NULL) {
|
|
*ResId = Size;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
#ifdef EXT2FS_DEBUG
|
|
/**
|
|
Dump the file system super block info.
|
|
|
|
@param[in] FileSystem pointer to filesystem.
|
|
|
|
@retval none
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
DumpSBlock (
|
|
IN M_EXT2FS *FileSystem
|
|
)
|
|
{
|
|
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsBlockCount = %u\n", FileSystem->Ext2Fs.Ext2FsBlockCount));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsFirstDataBlock = %u\n", FileSystem->Ext2Fs.Ext2FsFirstDataBlock));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsLogBlockSize = %u\n", FileSystem->Ext2Fs.Ext2FsLogBlockSize));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsBlocksPerGroup = %u\n", FileSystem->Ext2Fs.Ext2FsBlocksPerGroup));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsINodesPerGroup = %u\n", FileSystem->Ext2Fs.Ext2FsINodesPerGroup));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsMagic = 0x%x\n", FileSystem->Ext2Fs.Ext2FsMagic));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsRev = %u\n", FileSystem->Ext2Fs.Ext2FsRev));
|
|
|
|
if (FileSystem->Ext2Fs.Ext2FsRev == E2FS_REV1) {
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsFirstInode = %u\n",
|
|
FileSystem->Ext2Fs.Ext2FsFirstInode));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsInodeSize = %u\n",
|
|
FileSystem->Ext2Fs.Ext2FsInodeSize));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsFeaturesCompat = %u\n",
|
|
FileSystem->Ext2Fs.Ext2FsFeaturesCompat));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsFeaturesIncompat = %u\n",
|
|
FileSystem->Ext2Fs.Ext2FsFeaturesIncompat));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsFeaturesROCompat = %u\n",
|
|
FileSystem->Ext2Fs.Ext2FsFeaturesROCompat));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2Fs.Ext2FsRsvdGDBlock = %u\n",
|
|
FileSystem->Ext2Fs.Ext2FsRsvdGDBlock));
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2FsGDSize = %u\n", FileSystem->Ext2FsGDSize));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2FsBlockSize = %u\n", FileSystem->Ext2FsBlockSize));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2FsFsbtobd = %u\n", FileSystem->Ext2FsFsbtobd));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2FsNumCylinder = %u\n", FileSystem->Ext2FsNumCylinder));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2FsNumGrpDesBlock = %u\n", FileSystem->Ext2FsNumGrpDesBlock));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2FsInodesPerBlock = %u\n", FileSystem->Ext2FsInodesPerBlock));
|
|
DEBUG ((DEBUG_INFO, "FileSystem->Ext2FsInodesTablePerGrp = %u\n", FileSystem->Ext2FsInodesTablePerGrp));
|
|
}
|
|
|
|
/**
|
|
Dump the file group descriptor block info.
|
|
|
|
@param[in] FileSystem pointer to filesystem.
|
|
|
|
@retval none
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
DumpGroupDesBlock (
|
|
IN M_EXT2FS *FileSystem
|
|
)
|
|
{
|
|
INT32 Index;
|
|
EXT2GD *Ext2FsGrpDesEntry;
|
|
|
|
for (Index=0; Index < FileSystem->Ext2FsNumCylinder; Index++) {
|
|
Ext2FsGrpDesEntry = (EXT2GD*) ((UINT32) FileSystem->Ext2FsGrpDes + (Index * FileSystem->Ext2FsGDSize));
|
|
DEBUG ((DEBUG_INFO, "Ext2FsGrpDes[Index=%u]\n", Index));
|
|
DEBUG ((DEBUG_INFO, " Ext2BGDBlockBitmap %u\n", Ext2FsGrpDesEntry->Ext2BGDBlockBitmap));
|
|
DEBUG ((DEBUG_INFO, " Ext2BGDInodeBitmap %u\n", Ext2FsGrpDesEntry->Ext2BGDInodeBitmap));
|
|
DEBUG ((DEBUG_INFO, " Ext2BGDInodeTables %u\n", Ext2FsGrpDesEntry->Ext2BGDInodeTables));
|
|
DEBUG ((DEBUG_INFO, " Ext2BGDFreeBlocks %u\n", Ext2FsGrpDesEntry->Ext2BGDFreeBlocks));
|
|
DEBUG ((DEBUG_INFO, " Ext2BGDFreeInodes %u\n", Ext2FsGrpDesEntry->Ext2BGDFreeInodes));
|
|
DEBUG ((DEBUG_INFO, " Ext2BGDNumDir %u\n", Ext2FsGrpDesEntry->Ext2BGDNumDir));
|
|
if (FileSystem->Ext2FsGDSize > 32) {
|
|
DEBUG ((DEBUG_INFO, " Ext2BGDInodeTablesHi %u\n", Ext2FsGrpDesEntry->Ext2BGDInodeTablesHi));
|
|
}
|
|
}
|
|
}
|
|
#endif
|