Add EDK II Prime FatPkg New Feature: Support both Unicode Collation and Unicode Collation 2 Protocols Support both Component Name and Component Name 2 Protocol.

(based on FatPkg commit e51cd032db84a6fb1f44a0605f80d96f5fdf4bc6)

[jordan.l.justen@intel.com: Use script to relicense to 2-clause BSD]
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Acked-by: Mark Doran <mark.doran@intel.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Qing Huang 2007-12-20 09:16:45 +00:00 committed by Jordan Justen
parent f0dc69e61b
commit b9ec93308b
26 changed files with 9754 additions and 0 deletions

View File

@ -0,0 +1,355 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ComponentName.c
Abstract:
--*/
#include "Fat.h"
//
// EFI Component Name Functions
//
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 3066 or ISO 639-2 language code format.
@param DriverName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
FatComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param ControllerHandle[in] The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param ChildHandle[in] The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 3066 or ISO 639-2 language code format.
@param ControllerName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
FatComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gFatComponentName = {
FatComponentNameGetDriverName,
FatComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gFatComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) FatComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) FatComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mFatDriverNameTable[] = {
{
"eng;en",
L"FAT File System Driver"
},
{
NULL,
NULL
}
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mFatControllerNameTable[] = {
{
"eng;en",
L"FAT File System"
},
{
NULL,
NULL
}
};
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 3066 or ISO 639-2 language code format.
@param DriverName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
FatComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mFatDriverNameTable,
DriverName,
(BOOLEAN)(This == &gFatComponentName)
);
}
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param ControllerHandle[in] The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param ChildHandle[in] The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param Language[in] A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 3066 or ISO 639-2 language code format.
@param ControllerName[out] A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
FatComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
EFI_STATUS Status;
//
// This is a device driver, so ChildHandle must be NULL.
//
if (ChildHandle != NULL) {
return EFI_UNSUPPORTED;
}
//
// Make sure this driver is currently managing ControllHandle
//
Status = EfiTestManagedDevice (
ControllerHandle,
gFatDriverBinding.DriverBindingHandle,
&gEfiDiskIoProtocolGuid
);
if (EFI_ERROR (Status)) {
return Status;
}
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mFatControllerNameTable,
ControllerName,
(BOOLEAN)(This == &gFatComponentName)
);
}

View File

@ -0,0 +1,50 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Data.c
Abstract:
Global data in the FAT Filesystem driver
Revision History
--*/
#include "Fat.h"
//
// Globals
//
//
// FatFsLock - Global lock for synchronizing all requests.
//
EFI_LOCK FatFsLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_CALLBACK);
//
// Filesystem interface functions
//
EFI_FILE FatFileInterface = {
EFI_FILE_PROTOCOL_REVISION,
FatOpen,
FatClose,
FatDelete,
FatRead,
FatWrite,
FatGetPosition,
FatSetPosition,
FatGetInfo,
FatSetInfo,
FatFlush
};

View File

@ -0,0 +1,80 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
debug.c
Abstract:
Debug functions for fat driver
Revision History
--*/
#include "Fat.h"
VOID
FatDumpFatTable (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Dump all the FAT Entry of the FAT table in the volume
Arguments:
Volume - The volume whose FAT info will be dumped
Returns:
None
--*/
{
UINTN EntryValue;
UINTN MaxIndex;
UINTN Index;
CHAR16 *Pointer;
MaxIndex = Volume->MaxCluster + 2;
Print (L"Dump of Fat Table, MaxCluster %x\n", MaxIndex);
for (Index = 0; Index < MaxIndex; Index++) {
EntryValue = FatGetFatEntry (Volume, Index);
if (EntryValue != FAT_CLUSTER_FREE) {
Pointer = NULL;
switch (EntryValue) {
case FAT_CLUSTER_RESERVED:
Pointer = L"RESREVED";
break;
case FAT_CLUSTER_BAD:
Pointer = L"BAD";
break;
}
if (FAT_END_OF_FAT_CHAIN (EntryValue)) {
Pointer = L"LAST";
}
if (Pointer != NULL) {
Print (L"Entry %x = %s\n", Index, Pointer);
} else {
Print (L"Entry %x = %x\n", Index, EntryValue);
}
}
}
}

View File

@ -0,0 +1,138 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
delete.c
Abstract:
Function that deletes a file
Revision History
--*/
#include "Fat.h"
EFI_STATUS
EFIAPI
FatDelete (
IN EFI_FILE *FHand
)
/*++
Routine Description:
Deletes the file & Closes the file handle.
Arguments:
FHand - Handle to the file to delete.
Returns:
EFI_SUCCESS - Delete the file successfully.
EFI_WARN_DELETE_FAILURE - Fail to delete the file.
--*/
{
FAT_IFILE *IFile;
FAT_OFILE *OFile;
FAT_DIRENT *DirEnt;
EFI_STATUS Status;
UINTN Round;
IFile = IFILE_FROM_FHAND (FHand);
OFile = IFile->OFile;
//
// Lock the volume
//
FatAcquireLock ();
//
// If the file is read-only, then don't delete it
//
if (IFile->ReadOnly) {
Status = EFI_WRITE_PROTECTED;
goto Done;
}
//
// If the file is the root dir, then don't delete it
//
if (OFile->Parent == NULL) {
Status = EFI_ACCESS_DENIED;
goto Done;
}
//
// If the file has a permanant error, skip the delete
//
Status = OFile->Error;
if (!EFI_ERROR (Status)) {
//
// If this is a directory, make sure it's empty before
// allowing it to be deleted
//
if (OFile->ODir != NULL) {
//
// We do not allow to delete nonempty directory
//
FatResetODirCursor (OFile);
for (Round = 0; Round < 3; Round++) {
Status = FatGetNextDirEnt (OFile, &DirEnt);
if ((EFI_ERROR (Status)) ||
((Round < 2) && (DirEnt == NULL || !FatIsDotDirEnt (DirEnt))) ||
((Round == 2) && (DirEnt != NULL))
) {
Status = EFI_ACCESS_DENIED;
goto Done;
}
}
}
//
// Return the file's space by setting its size to 0
//
FatTruncateOFile (OFile, 0);
//
// Free the directory entry for this file
//
Status = FatRemoveDirEnt (OFile->Parent, OFile->DirEnt);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Set a permanent error for this OFile in case there
// are still opened IFiles attached
//
OFile->Error = EFI_NOT_FOUND;
} else if (OFile->Error == EFI_NOT_FOUND) {
Status = EFI_SUCCESS;
}
Done:
//
// Always close the handle
//
FatIFileClose (IFile);
//
// Done
//
Status = FatCleanupVolume (OFile->Volume, NULL, Status);
FatReleaseLock ();
if (EFI_ERROR (Status)) {
Status = EFI_WARN_DELETE_FAILURE;
}
return Status;
}

View File

@ -0,0 +1,238 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
DirectoryCache.c
Abstract:
Functions for directory cache operation
Revision History
--*/
#include "Fat.h"
STATIC
VOID
FatFreeODir (
IN FAT_ODIR *ODir
)
/*++
Routine Description:
Free the directory structure and release the memory.
Arguments:
ODir - The directory to be freed.
Returns:
None.
--*/
{
FAT_DIRENT *DirEnt;
//
// Release Directory Entry Nodes
//
while (!IsListEmpty (&ODir->ChildList)) {
DirEnt = DIRENT_FROM_LINK (ODir->ChildList.ForwardLink);
RemoveEntryList (&DirEnt->Link);
//
// Make sure the OFile has been closed
//
ASSERT (DirEnt->OFile == NULL);
FatFreeDirEnt (DirEnt);
}
FreePool (ODir);
}
STATIC
FAT_ODIR *
FatAllocateODir (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Allocate the directory structure.
Arguments:
OFile - The corresponding OFile.
Returns:
None.
--*/
{
FAT_ODIR *ODir;
ODir = AllocateZeroPool (sizeof (FAT_ODIR));
if (ODir != NULL) {
//
// Initialize the directory entry list
//
ODir->Signature = FAT_ODIR_SIGNATURE;
InitializeListHead (&ODir->ChildList);
ODir->CurrentCursor = &ODir->ChildList;
}
return ODir;
}
VOID
FatDiscardODir (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Discard the directory structure when an OFile will be freed.
Volume will cache this directory if the OFile does not represent a deleted file.
Arguments:
OFile - The OFile whose directory structure is to be discarded.
Returns:
None.
--*/
{
FAT_ODIR *ODir;
FAT_VOLUME *Volume;
Volume = OFile->Volume;
ODir = OFile->ODir;
if (!OFile->DirEnt->Invalid) {
//
// If OFile does not represent a deleted file, then we will cache the directory
// We use OFile's first cluster as the directory's tag
//
ODir->DirCacheTag = OFile->FileCluster;
InsertHeadList (&Volume->DirCacheList, &ODir->DirCacheLink);
if (Volume->DirCacheCount == FAT_MAX_DIR_CACHE_COUNT) {
//
// Replace the least recent used directory
//
ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
RemoveEntryList (&ODir->DirCacheLink);
} else {
//
// No need to find a replace
//
Volume->DirCacheCount++;
ODir = NULL;
}
}
//
// Release ODir Structure
//
if (ODir != NULL) {
FatFreeODir (ODir);
}
}
VOID
FatRequestODir (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Request the directory structure when an OFile is newly generated.
If the directory structure is cached by volume, then just return this directory;
Otherwise, allocate a new one for OFile.
Arguments:
OFile - The OFile which requests directory structure.
Returns:
None.
--*/
{
UINTN DirCacheTag;
FAT_VOLUME *Volume;
FAT_ODIR *ODir;
FAT_ODIR *CurrentODir;
LIST_ENTRY *CurrentODirLink;
Volume = OFile->Volume;
ODir = NULL;
DirCacheTag = OFile->FileCluster;
for (CurrentODirLink = Volume->DirCacheList.ForwardLink;
CurrentODirLink != &Volume->DirCacheList;
CurrentODirLink = CurrentODirLink->ForwardLink
) {
CurrentODir = ODIR_FROM_DIRCACHELINK (CurrentODirLink);
if (CurrentODir->DirCacheTag == DirCacheTag) {
RemoveEntryList (&CurrentODir->DirCacheLink);
Volume->DirCacheCount--;
ODir = CurrentODir;
break;
}
}
if (ODir == NULL) {
//
// This directory is not cached, then allocate a new one
//
ODir = FatAllocateODir (OFile);
}
OFile->ODir = ODir;
}
VOID
FatCleanupODirCache (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Clean up all the cached directory structures when the volume is going to be abandoned.
Arguments:
Volume - FAT file system volume.
Returns:
None.
--*/
{
FAT_ODIR *ODir;
while (Volume->DirCacheCount > 0) {
ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
RemoveEntryList (&ODir->DirCacheLink);
FatFreeODir (ODir);
Volume->DirCacheCount--;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,541 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
DiskCache.c
Abstract:
Cache implementation for EFI FAT File system driver
Revision History
--*/
#include "Fat.h"
STATIC
VOID
FatFlushDataCacheRange (
IN FAT_VOLUME *Volume,
IN IO_MODE IoMode,
IN UINTN StartPageNo,
IN UINTN EndPageNo,
OUT UINT8 *Buffer
)
/*++
Routine Description:
This function is used by the Data Cache.
When this function is called by write command, all entries in this range
are older than the contents in disk, so they are invalid; just mark them invalid.
When this function is called by read command, if any entry in this range
is dirty, it means that the relative info directly readed from media is older than
than the info in the cache; So need to update the relative info in the Buffer.
Arguments:
Volume - FAT file system volume.
IoMode - This function is called by read command or write command
StartPageNo - First PageNo to be checked in the cache.
EndPageNo - Last PageNo to be checked in the cache.
Buffer - The user buffer need to update. Only when doing the read command
and there is dirty cache in the cache range, this parameter will be used.
Returns:
None.
--*/
{
UINTN PageNo;
UINTN GroupNo;
UINTN GroupMask;
UINTN PageSize;
UINT8 PageAlignment;
DISK_CACHE *DiskCache;
CACHE_TAG *CacheTag;
UINT8 *BaseAddress;
DiskCache = &Volume->DiskCache[CACHE_DATA];
BaseAddress = DiskCache->CacheBase;
GroupMask = DiskCache->GroupMask;
PageAlignment = DiskCache->PageAlignment;
PageSize = (UINTN)1 << PageAlignment;
for (PageNo = StartPageNo; PageNo < EndPageNo; PageNo++) {
GroupNo = PageNo & GroupMask;
CacheTag = &DiskCache->CacheTag[GroupNo];
if (CacheTag->RealSize > 0 && CacheTag->PageNo == PageNo) {
//
// When reading data form disk directly, if some dirty data
// in cache is in this rang, this data in the Buffer need to
// be updated with the cache's dirty data.
//
if (IoMode == READ_DISK) {
if (CacheTag->Dirty) {
CopyMem (
Buffer + ((PageNo - StartPageNo) << PageAlignment),
BaseAddress + (GroupNo << PageAlignment),
PageSize
);
}
} else {
//
// Make all valid entries in this range invalid.
//
CacheTag->RealSize = 0;
}
}
}
}
STATIC
EFI_STATUS
FatExchangeCachePage (
IN FAT_VOLUME *Volume,
IN CACHE_DATA_TYPE DataType,
IN IO_MODE IoMode,
IN CACHE_TAG *CacheTag
)
/*++
Routine Description:
Exchange the cache page with the image on the disk
Arguments:
Volume - FAT file system volume.
DataType - Indicate the cache type.
IoMode - Indicate whether to load this page from disk or store this page to disk.
CacheTag - The Cache Tag for the current cache page.
Returns:
EFI_SUCCESS - Cache page exchanged successfully.
Others - An error occurred when exchanging cache page.
--*/
{
EFI_STATUS Status;
UINTN GroupNo;
UINTN PageNo;
UINTN WriteCount;
UINTN RealSize;
UINT64 EntryPos;
UINT64 MaxSize;
DISK_CACHE *DiskCache;
VOID *PageAddress;
UINT8 PageAlignment;
DiskCache = &Volume->DiskCache[DataType];
PageNo = CacheTag->PageNo;
GroupNo = PageNo & DiskCache->GroupMask;
PageAlignment = DiskCache->PageAlignment;
PageAddress = DiskCache->CacheBase + (GroupNo << PageAlignment);
EntryPos = DiskCache->BaseAddress + LShiftU64 (PageNo, PageAlignment);
RealSize = CacheTag->RealSize;
if (IoMode == READ_DISK) {
RealSize = (UINTN)1 << PageAlignment;
MaxSize = DiskCache->LimitAddress - EntryPos;
if (MaxSize < RealSize) {
DEBUG ((EFI_D_INFO, "FatDiskIo: Cache Page OutBound occurred! \n"));
RealSize = (UINTN) MaxSize;
}
}
WriteCount = 1;
if (DataType == CACHE_FAT && IoMode == WRITE_DISK) {
WriteCount = Volume->NumFats;
}
do {
//
// Only fat table writing will execute more than once
//
Status = FatDiskIo (Volume, IoMode, EntryPos, RealSize, PageAddress);
if (EFI_ERROR (Status)) {
return Status;
}
EntryPos += Volume->FatSize;
} while (--WriteCount > 0);
CacheTag->Dirty = FALSE;
CacheTag->RealSize = RealSize;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FatGetCachePage (
IN FAT_VOLUME *Volume,
IN CACHE_DATA_TYPE CacheDataType,
IN UINTN PageNo,
IN CACHE_TAG *CacheTag
)
/*++
Routine Description:
Get one cache page by specified PageNo.
Arguments:
Volume - FAT file system volume.
CacheDataType - The cache type: CACHE_FAT or CACHE_DATA.
PageNo - PageNo to match with the cache.
CacheTag - The Cache Tag for the current cache page.
Returns:
EFI_SUCCESS - Get the cache page successfully.
other - An error occurred when accessing data.
--*/
{
EFI_STATUS Status;
UINTN OldPageNo;
OldPageNo = CacheTag->PageNo;
if (CacheTag->RealSize > 0 && OldPageNo == PageNo) {
//
// Cache Hit occurred
//
return EFI_SUCCESS;
}
//
// Write dirty cache page back to disk
//
if (CacheTag->RealSize > 0 && CacheTag->Dirty) {
Status = FatExchangeCachePage (Volume, CacheDataType, WRITE_DISK, CacheTag);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Load new data from disk;
//
CacheTag->PageNo = PageNo;
Status = FatExchangeCachePage (Volume, CacheDataType, READ_DISK, CacheTag);
return Status;
}
STATIC
EFI_STATUS
FatAccessUnalignedCachePage (
IN FAT_VOLUME *Volume,
IN CACHE_DATA_TYPE CacheDataType,
IN IO_MODE IoMode,
IN UINTN PageNo,
IN UINTN Offset,
IN UINTN Length,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Read Length bytes from the position of Offset into Buffer, or
write Length bytes from Buffer into the position of Offset.
Arguments:
Volume - FAT file system volume.
CacheDataType - The type of cache: CACHE_DATA or CACHE_FAT.
IoMode - Indicate the type of disk access.
PageNo - The number of unaligned cache page.
Offset - The starting byte of cache page.
Length - The number of bytes that is read or written
Buffer - Buffer containing cache data.
Returns:
EFI_SUCCESS - The data was accessed correctly.
Others - An error occurred when accessing unaligned cache page.
--*/
{
EFI_STATUS Status;
VOID *Source;
VOID *Destination;
DISK_CACHE *DiskCache;
CACHE_TAG *CacheTag;
UINTN GroupNo;
DiskCache = &Volume->DiskCache[CacheDataType];
GroupNo = PageNo & DiskCache->GroupMask;
CacheTag = &DiskCache->CacheTag[GroupNo];
Status = FatGetCachePage (Volume, CacheDataType, PageNo, CacheTag);
if (!EFI_ERROR (Status)) {
Source = DiskCache->CacheBase + (GroupNo << DiskCache->PageAlignment) + Offset;
Destination = Buffer;
if (IoMode != READ_DISK) {
CacheTag->Dirty = TRUE;
DiskCache->Dirty = TRUE;
Destination = Source;
Source = Buffer;
}
CopyMem (Destination, Source, Length);
}
return Status;
}
EFI_STATUS
FatAccessCache (
IN FAT_VOLUME *Volume,
IN CACHE_DATA_TYPE CacheDataType,
IN IO_MODE IoMode,
IN UINT64 Offset,
IN UINTN BufferSize,
IN OUT UINT8 *Buffer
)
/*++
Routine Description:
Read BufferSize bytes from the position of Offset into Buffer,
or write BufferSize bytes from Buffer into the position of Offset.
Base on the parameter of CACHE_DATA_TYPE, the data access will be divided into
the access of FAT cache (CACHE_FAT) and the access of Data cache (CACHE_DATA):
1. Access of FAT cache (CACHE_FAT): Access the data in the FAT cache, if there is cache
page hit, just return the cache page; else update the related cache page and return
the right cache page.
2. Access of Data cache (CACHE_DATA):
The access data will be divided into UnderRun data, Aligned data and OverRun data;
The UnderRun data and OverRun data will be accessed by the Data cache,
but the Aligned data will be accessed with disk directly.
Arguments:
Volume - FAT file system volume.
CacheDataType - The type of cache: CACHE_DATA or CACHE_FAT.
IoMode - Indicate the type of disk access.
Offset - The starting byte offset to read from.
BufferSize - Size of Buffer.
Buffer - Buffer containing cache data.
Returns:
EFI_SUCCESS - The data was accessed correctly.
EFI_MEDIA_CHANGED - The MediaId does not match the current device.
Others - An error occurred when accessing cache.
--*/
{
EFI_STATUS Status;
UINTN PageSize;
UINTN UnderRun;
UINTN OverRun;
UINTN AlignedSize;
UINTN Length;
UINTN PageNo;
UINTN AlignedPageCount;
UINTN OverRunPageNo;
DISK_CACHE *DiskCache;
UINT64 EntryPos;
UINT8 PageAlignment;
ASSERT (Volume->CacheBuffer != NULL);
Status = EFI_SUCCESS;
DiskCache = &Volume->DiskCache[CacheDataType];
EntryPos = Offset - DiskCache->BaseAddress;
PageAlignment = DiskCache->PageAlignment;
PageSize = (UINTN)1 << PageAlignment;
PageNo = (UINTN) RShiftU64 (EntryPos, PageAlignment);
UnderRun = ((UINTN) EntryPos) & (PageSize - 1);
if (UnderRun > 0) {
Length = PageSize - UnderRun;
if (Length > BufferSize) {
Length = BufferSize;
}
Status = FatAccessUnalignedCachePage (Volume, CacheDataType, IoMode, PageNo, UnderRun, Length, Buffer);
if (EFI_ERROR (Status)) {
return Status;
}
Buffer += Length;
BufferSize -= Length;
PageNo++;
}
AlignedPageCount = BufferSize >> PageAlignment;
OverRunPageNo = PageNo + AlignedPageCount;
//
// The access of the Aligned data
//
if (AlignedPageCount > 0) {
//
// Accessing fat table cannot have alignment data
//
ASSERT (CacheDataType == CACHE_DATA);
EntryPos = Volume->RootPos + LShiftU64 (PageNo, PageAlignment);
AlignedSize = AlignedPageCount << PageAlignment;
Status = FatDiskIo (Volume, IoMode, EntryPos, AlignedSize, Buffer);
if (EFI_ERROR (Status)) {
return Status;
}
//
// If these access data over laps the relative cache range, these cache pages need
// to be updated.
//
FatFlushDataCacheRange (Volume, IoMode, PageNo, OverRunPageNo, Buffer);
Buffer += AlignedSize;
BufferSize -= AlignedSize;
}
//
// The access of the OverRun data
//
OverRun = BufferSize;
if (OverRun > 0) {
//
// Last read is not a complete page
//
Status = FatAccessUnalignedCachePage (Volume, CacheDataType, IoMode, OverRunPageNo, 0, OverRun, Buffer);
}
return Status;
}
EFI_STATUS
FatVolumeFlushCache (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Flush all the dirty cache back, include the FAT cache and the Data cache.
Arguments:
Volume - FAT file system volume.
Returns:
EFI_SUCCESS - Flush all the dirty cache back successfully
other - An error occurred when writing the data into the disk
--*/
{
EFI_STATUS Status;
CACHE_DATA_TYPE CacheDataType;
UINTN GroupIndex;
UINTN GroupMask;
DISK_CACHE *DiskCache;
CACHE_TAG *CacheTag;
for (CacheDataType = (CACHE_DATA_TYPE) 0; CacheDataType < CACHE_MAX_TYPE; CacheDataType++) {
DiskCache = &Volume->DiskCache[CacheDataType];
if (DiskCache->Dirty) {
//
// Data cache or fat cache is dirty, write the dirty data back
//
GroupMask = DiskCache->GroupMask;
for (GroupIndex = 0; GroupIndex <= GroupMask; GroupIndex++) {
CacheTag = &DiskCache->CacheTag[GroupIndex];
if (CacheTag->RealSize > 0 && CacheTag->Dirty) {
//
// Write back all Dirty Data Cache Page to disk
//
Status = FatExchangeCachePage (Volume, CacheDataType, WRITE_DISK, CacheTag);
if (EFI_ERROR (Status)) {
return Status;
}
}
}
DiskCache->Dirty = FALSE;
}
}
//
// Flush the block device.
//
Status = Volume->BlockIo->FlushBlocks (Volume->BlockIo);
return Status;
}
EFI_STATUS
FatInitializeDiskCache (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Initialize the disk cache according to Volume's FatType.
Arguments:
Volume - FAT file system volume.
Returns:
EFI_SUCCESS - The disk cache is successfully initialized.
EFI_OUT_OF_RESOURCES - Not enough memory to allocate disk cache.
--*/
{
DISK_CACHE *DiskCache;
UINTN FatCacheGroupCount;
UINTN DataCacheSize;
UINTN FatCacheSize;
UINT8 *CacheBuffer;
DiskCache = Volume->DiskCache;
//
// Configure the parameters of disk cache
//
if (Volume->FatType == FAT12) {
FatCacheGroupCount = FAT_FATCACHE_GROUP_MIN_COUNT;
DiskCache[CACHE_FAT].PageAlignment = FAT_FATCACHE_PAGE_MIN_ALIGNMENT;
DiskCache[CACHE_DATA].PageAlignment = FAT_DATACACHE_PAGE_MIN_ALIGNMENT;
} else {
FatCacheGroupCount = FAT_FATCACHE_GROUP_MAX_COUNT;
DiskCache[CACHE_FAT].PageAlignment = FAT_FATCACHE_PAGE_MAX_ALIGNMENT;
DiskCache[CACHE_DATA].PageAlignment = FAT_DATACACHE_PAGE_MAX_ALIGNMENT;
}
DiskCache[CACHE_DATA].GroupMask = FAT_DATACACHE_GROUP_COUNT - 1;
DiskCache[CACHE_DATA].BaseAddress = Volume->RootPos;
DiskCache[CACHE_DATA].LimitAddress = Volume->VolumeSize;
DiskCache[CACHE_FAT].GroupMask = FatCacheGroupCount - 1;
DiskCache[CACHE_FAT].BaseAddress = Volume->FatPos;
DiskCache[CACHE_FAT].LimitAddress = Volume->FatPos + Volume->FatSize;
FatCacheSize = FatCacheGroupCount << DiskCache[CACHE_FAT].PageAlignment;
DataCacheSize = FAT_DATACACHE_GROUP_COUNT << DiskCache[CACHE_DATA].PageAlignment;
//
// Allocate the Fat Cache buffer
//
CacheBuffer = AllocatePool (FatCacheSize + DataCacheSize);
if (CacheBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Volume->CacheBuffer = CacheBuffer;
DiskCache[CACHE_FAT].CacheBase = CacheBuffer;
DiskCache[CACHE_DATA].CacheBase = CacheBuffer + FatCacheSize;
return EFI_SUCCESS;
}

393
FatPkg/EnhancedFatDxe/Fat.c Normal file
View File

@ -0,0 +1,393 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Fat.c
Abstract:
Fat File System driver routines that support EFI driver model
--*/
#include "Fat.h"
EFI_STATUS
EFIAPI
FatEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
EFI_STATUS
EFIAPI
FatUnload (
IN EFI_HANDLE ImageHandle
);
EFI_STATUS
EFIAPI
FatDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
FatDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
FatDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
//
// DriverBinding protocol instance
//
EFI_DRIVER_BINDING_PROTOCOL gFatDriverBinding = {
FatDriverBindingSupported,
FatDriverBindingStart,
FatDriverBindingStop,
0xa,
NULL,
NULL
};
EFI_STATUS
EFIAPI
FatEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Register Driver Binding protocol for this driver.
Arguments:
ImageHandle - Handle for the image of this driver.
SystemTable - Pointer to the EFI System Table.
Returns:
EFI_SUCCESS - Driver loaded.
other - Driver not loaded.
--*/
{
EFI_STATUS Status;
//
// Initialize the EFI Driver Library
//
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gFatDriverBinding,
ImageHandle,
&gFatComponentName,
&gFatComponentName2
);
ASSERT_EFI_ERROR (Status);
return Status;
}
EFI_STATUS
EFIAPI
FatUnload (
IN EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Unload function for this image. Uninstall DriverBinding protocol.
Arguments:
ImageHandle - Handle for the image of this driver.
Returns:
EFI_SUCCESS - Driver unloaded successfully.
other - Driver can not unloaded.
--*/
{
EFI_STATUS Status;
EFI_HANDLE *DeviceHandleBuffer;
UINTN DeviceHandleCount;
UINTN Index;
Status = gBS->LocateHandleBuffer (
AllHandles,
NULL,
NULL,
&DeviceHandleCount,
&DeviceHandleBuffer
);
if (!EFI_ERROR (Status)) {
for (Index = 0; Index < DeviceHandleCount; Index++) {
Status = gBS->DisconnectController (
DeviceHandleBuffer[Index],
ImageHandle,
NULL
);
}
if (DeviceHandleBuffer != NULL) {
FreePool (DeviceHandleBuffer);
}
}
return Status;
}
EFI_STATUS
EFIAPI
FatDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Test to see if this driver can add a file system to ControllerHandle.
ControllerHandle must support both Disk IO and Block IO protocols.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of device to test.
RemainingDevicePath - Not used.
Returns:
EFI_SUCCESS - This driver supports this device.
EFI_ALREADY_STARTED - This driver is already running on this device.
other - This driver does not support this device.
--*/
{
EFI_STATUS Status;
EFI_DISK_IO_PROTOCOL *DiskIo;
//
// Open the IO Abstraction(s) needed to perform the supported test
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
(VOID **) &DiskIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Close the I/O Abstraction(s) used to perform the supported test
//
gBS->CloseProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
//
// Open the IO Abstraction(s) needed to perform the supported test
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiBlockIoProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
return Status;
}
EFI_STATUS
EFIAPI
FatDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Start this driver on ControllerHandle by opening a Block IO and Disk IO
protocol, reading Device Path. Add a Simple File System protocol to
ControllerHandle if the media contains a valid file system.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of device to bind driver to.
RemainingDevicePath - Not used.
Returns:
EFI_SUCCESS - This driver is added to DeviceHandle.
EFI_ALREADY_STARTED - This driver is already running on DeviceHandle.
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
other - This driver does not support this device.
--*/
{
EFI_STATUS Status;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_DISK_IO_PROTOCOL *DiskIo;
Status = InitializeUnicodeCollationSupport (This->DriverBindingHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Open our required BlockIo and DiskIo
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiBlockIoProtocolGuid,
(VOID **) &BlockIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
(VOID **) &DiskIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Allocate Volume structure. In FatAllocateVolume(), Resources
// are allocated with protocol installed and cached initialized
//
Status = FatAllocateVolume (ControllerHandle, DiskIo, BlockIo);
//
// When the media changes on a device it will Reinstall the BlockIo interaface.
// This will cause a call to our Stop(), and a subsequent reentrant call to our
// Start() successfully. We should leave the device open when this happen.
//
if (EFI_ERROR (Status)) {
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
}
}
return Status;
}
EFI_STATUS
EFIAPI
FatDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
/*++
Routine Description:
Stop this driver on ControllerHandle.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of device to stop driver on.
NumberOfChildren - Not used.
ChildHandleBuffer - Not used.
Returns:
EFI_SUCCESS - This driver is removed DeviceHandle.
other - This driver was not removed from this device.
--*/
{
EFI_STATUS Status;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
FAT_VOLUME *Volume;
//
// Get our context back
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiSimpleFileSystemProtocolGuid,
(VOID **) &FileSystem,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR (Status)) {
Volume = VOLUME_FROM_VOL_INTERFACE (FileSystem);
Status = FatAbandonVolume (Volume);
if (EFI_ERROR (Status)) {
return Status;
}
}
Status = gBS->CloseProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
return Status;
}

1119
FatPkg/EnhancedFatDxe/Fat.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
#/** @file
# Component description file for FAT module.
#
# This UEFI driver detects the FAT file system in the disk.
# It also produces the Simple File System protocol for the consumer to
# perform file and directory operations on the disk.
# Copyright (c) 2007, Intel Corporation
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Fat
FILE_GUID = 961578FE-B6B7-44c3-AF35-6BC705CD2B1F
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = FatEntryPoint
UNLOAD_IMAGE = FatUnload
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
# DRIVER_BINDING = gFatDriverBinding
# COMPONENT_NAME = gFatComponentName
# COMPONENT_NAME2 = gFatComponentName2
#
[Sources.common]
DirectoryCache.c
DiskCache.c
FileName.c
Hash.c
DirectoryManage.c
ComponentName.c
FatFileSystem.h
Fat.h
ReadWrite.c
OpenVolume.c
Open.c
Misc.c
Init.c
Info.c
FileSpace.c
Flush.c
Fat.c
Delete.c
Data.c
UnicodeCollation.c
[Packages]
MdePkg/MdePkg.dec
FatPkg/FatPkg.dec
[LibraryClasses]
UefiRuntimeServicesTableLib
UefiBootServicesTableLib
MemoryAllocationLib
BaseMemoryLib
BaseLib
UefiLib
UefiDriverEntryPoint
DebugLib
PcdLib
[Guids]
gEfiFileInfoGuid
gEfiFileSystemInfoGuid
gEfiFileSystemVolumeLabelInfoIdGuid
gEfiGlobalVariableGuid
[Protocols]
gEfiDiskIoProtocolGuid
gEfiBlockIoProtocolGuid
gEfiSimpleFileSystemProtocolGuid
gEfiUnicodeCollationProtocolGuid
gEfiUnicodeCollation2ProtocolGuid
[FeaturePcd]
gEfiFatPkgTokenSpaceGuid.PcdUnicodeCollationSupport
gEfiFatPkgTokenSpaceGuid.PcdUnicodeCollation2Support
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang

View File

@ -0,0 +1,221 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
FatFileSystem.h
Abstract:
Definitions for on-disk FAT structures
Revision History
--*/
#ifndef _FATFILESYSTEM_H_
#define _FATFILESYSTEM_H_
#pragma pack(1)
//
// FAT info signature
//
#define FAT_INFO_SIGNATURE 0x41615252
#define FAT_INFO_BEGIN_SIGNATURE 0x61417272
#define FAT_INFO_END_SIGNATURE 0xAA550000
//
// FAT entry values
//
#define FAT_CLUSTER_SPECIAL_EXT (-1 & (~0xF))
#define FAT_CLUSTER_SPECIAL ((FAT_CLUSTER_SPECIAL_EXT) | 0x07)
#define FAT_CLUSTER_FREE 0
#define FAT_CLUSTER_RESERVED (FAT_CLUSTER_SPECIAL)
#define FAT_CLUSTER_BAD (FAT_CLUSTER_SPECIAL)
#define FAT_CLUSTER_LAST (-1)
#define FAT_END_OF_FAT_CHAIN(Cluster) ((Cluster) > (FAT_CLUSTER_SPECIAL))
#define FAT_MIN_CLUSTER 2
#define FAT_MAX_FAT12_CLUSTER 0xFF5
#define FAT_MAX_FAT16_CLUSTER 0xFFF5
#define FAT_CLUSTER_SPECIAL_FAT12 0xFF7
#define FAT_CLUSTER_SPECIAL_FAT16 0xFFF7
#define FAT_CLUSTER_SPECIAL_FAT32 0x0FFFFFF7
#define FAT_CLUSTER_MASK_FAT12 0xFFF
#define FAT_CLUSTER_UNMASK_FAT12 0xF000
#define FAT_CLUSTER_MASK_FAT32 0x0FFFFFFF
#define FAT_CLUSTER_UNMASK_FAT32 0xF0000000
#define FAT_POS_FAT12(a) ((a) * 3 / 2)
#define FAT_POS_FAT16(a) ((a) * 2)
#define FAT_POS_FAT32(a) ((a) * 4)
#define FAT_ODD_CLUSTER_FAT12(a) (((a) & 1) != 0)
//
// FAT attribute define
//
#define FAT_ATTRIBUTE_READ_ONLY 0x01
#define FAT_ATTRIBUTE_HIDDEN 0x02
#define FAT_ATTRIBUTE_SYSTEM 0x04
#define FAT_ATTRIBUTE_VOLUME_ID 0x08
#define FAT_ATTRIBUTE_DIRECTORY 0x10
#define FAT_ATTRIBUTE_ARCHIVE 0x20
#define FAT_ATTRIBUTE_DEVICE 0x40
#define FAT_ATTRIBUTE_LFN 0x0F
//
// Some Long File Name definitions
//
#define FAT_LFN_LAST 0x40 // Ordinal field
#define MAX_LFN_ENTRIES 20
#define LFN_CHAR1_LEN 5
#define LFN_CHAR2_LEN 6
#define LFN_CHAR3_LEN 2
#define LFN_CHAR_TOTAL (LFN_CHAR1_LEN + LFN_CHAR2_LEN + LFN_CHAR3_LEN)
#define LFN_ENTRY_NUMBER(a) (((a) + LFN_CHAR_TOTAL - 1) / LFN_CHAR_TOTAL)
//
// Some 8.3 File Name definitions
//
#define FAT_MAIN_NAME_LEN 8
#define FAT_EXTEND_NAME_LEN 3
#define FAT_NAME_LEN (FAT_MAIN_NAME_LEN + FAT_EXTEND_NAME_LEN)
//
// Some directory entry information
//
#define FAT_ENTRY_INFO_OFFSET 13
#define DELETE_ENTRY_MARK 0xE5
#define EMPTY_ENTRY_MARK 0x00
//
// Volume dirty Mask
//
#define FAT16_DIRTY_MASK 0x7fff
#define FAT32_DIRTY_MASK 0xf7ffffff
//
// internal flag
//
#define FAT_CASE_MIXED 0x01
#define FAT_CASE_NAME_LOWER 0x08
#define FAT_CASE_EXT_LOWER 0x10
typedef struct {
UINT8 Ia32Jump[3];
CHAR8 OemId[8];
UINT16 SectorSize;
UINT8 SectorsPerCluster;
UINT16 ReservedSectors;
UINT8 NumFats;
UINT16 RootEntries; // < FAT32, root dir is fixed size
UINT16 Sectors;
UINT8 Media;
UINT16 SectorsPerFat; // < FAT32
UINT16 SectorsPerTrack; // (ignored)
UINT16 Heads; // (ignored)
UINT32 HiddenSectors; // (ignored)
UINT32 LargeSectors; // Used if Sectors==0
} FAT_BOOT_SECTOR_BASIC;
typedef struct {
UINT8 PhysicalDriveNumber; // (ignored)
UINT8 CurrentHead; // holds boot_sector_dirty bit
UINT8 Signature; // (ignored)
CHAR8 Id[4];
CHAR8 FatLabel[11];
CHAR8 SystemId[8];
} FAT_BOOT_SECTOR_EXT;
typedef struct {
UINT32 LargeSectorsPerFat; // FAT32
UINT16 ExtendedFlags; // FAT32 (ignored)
UINT16 FsVersion; // FAT32 (ignored)
UINT32 RootDirFirstCluster; // FAT32
UINT16 FsInfoSector; // FAT32
UINT16 BackupBootSector; // FAT32
UINT8 Reserved[12]; // FAT32 (ignored)
UINT8 PhysicalDriveNumber; // (ignored)
UINT8 CurrentHead; // holds boot_sector_dirty bit
UINT8 Signature; // (ignored)
CHAR8 Id[4];
CHAR8 FatLabel[11];
CHAR8 SystemId[8];
} FAT32_BOOT_SECTOR_EXT;
typedef struct {
FAT_BOOT_SECTOR_BASIC FatBsb;
union {
FAT_BOOT_SECTOR_EXT FatBse;
FAT32_BOOT_SECTOR_EXT Fat32Bse;
} FatBse;
} FAT_BOOT_SECTOR;
//
// FAT Info Structure
//
typedef struct {
UINT32 ClusterCount;
UINT32 NextCluster;
} FAT_FREE_INFO;
typedef struct {
UINT32 Signature;
UINT8 ExtraBootCode[480];
UINT32 InfoBeginSignature;
FAT_FREE_INFO FreeInfo;
UINT8 Reserved[12];
UINT32 InfoEndSignature;
} FAT_INFO_SECTOR;
//
// Directory Entry
//
#define FAT_MAX_YEAR_FROM_1980 0x7f
typedef struct {
UINT16 Day : 5;
UINT16 Month : 4;
UINT16 Year : 7; // From 1980
} FAT_DATE;
typedef struct {
UINT16 DoubleSecond : 5;
UINT16 Minute : 6;
UINT16 Hour : 5;
} FAT_TIME;
typedef struct {
FAT_TIME Time;
FAT_DATE Date;
} FAT_DATE_TIME;
typedef struct {
CHAR8 FileName[11]; // 8.3 filename
UINT8 Attributes;
UINT8 CaseFlag;
UINT8 CreateMillisecond; // (creation milliseconds - ignored)
FAT_DATE_TIME FileCreateTime;
FAT_DATE FileLastAccess;
UINT16 FileClusterHigh; // >= FAT32
FAT_DATE_TIME FileModificationTime;
UINT16 FileCluster;
UINT32 FileSize;
} FAT_DIRECTORY_ENTRY;
typedef struct {
UINT8 Ordinal;
CHAR8 Name1[10]; // (Really 5 chars, but not WCHAR aligned)
UINT8 Attributes;
UINT8 Type;
UINT8 Checksum;
CHAR16 Name2[6];
UINT16 MustBeZero;
CHAR16 Name3[2];
} FAT_DIRECTORY_LFN;
#pragma pack()
#endif

View File

@ -0,0 +1,583 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
FileName.c
Abstract:
Functions for manipulating file names
Revision History
--*/
#include "Fat.h"
BOOLEAN
FatCheckIs8Dot3Name (
IN CHAR16 *FileName,
OUT CHAR8 *File8Dot3Name
)
/*++
Routine Description:
This function checks whether the input FileName is a valid 8.3 short name.
If the input FileName is a valid 8.3, the output is the 8.3 short name;
otherwise, the output is the base tag of 8.3 short name.
Arguments:
FileName - The input unicode filename.
File8Dot3Name - The output ascii 8.3 short name or base tag of 8.3 short name.
Returns:
TRUE - The input unicode filename is a valid 8.3 short name.
FALSE - The input unicode filename is not a valid 8.3 short name.
--*/
{
BOOLEAN PossibleShortName;
CHAR16 *TempName;
CHAR16 *ExtendName;
CHAR16 *SeparateDot;
UINTN MainNameLen;
UINTN ExtendNameLen;
PossibleShortName = TRUE;
SeparateDot = NULL;
SetMem (File8Dot3Name, FAT_NAME_LEN, ' ');
for (TempName = FileName; *TempName; TempName++) {
if (*TempName == L'.') {
SeparateDot = TempName;
}
}
if (SeparateDot == NULL) {
//
// Extended filename is not detected
//
MainNameLen = TempName - FileName;
ExtendName = TempName;
ExtendNameLen = 0;
} else {
//
// Extended filename is detected
//
MainNameLen = SeparateDot - FileName;
ExtendName = SeparateDot + 1;
ExtendNameLen = TempName - ExtendName;
}
//
// We scan the filename for the second time
// to check if there exists any extra blanks and dots
//
while (--TempName >= FileName) {
if ((*TempName == L'.' || *TempName == L' ') && (TempName != SeparateDot)) {
//
// There exist extra blanks and dots
//
PossibleShortName = FALSE;
}
}
if (MainNameLen == 0) {
PossibleShortName = FALSE;
}
if (MainNameLen > FAT_MAIN_NAME_LEN) {
PossibleShortName = FALSE;
MainNameLen = FAT_MAIN_NAME_LEN;
}
if (ExtendNameLen > FAT_EXTEND_NAME_LEN) {
PossibleShortName = FALSE;
ExtendNameLen = FAT_EXTEND_NAME_LEN;
}
if (FatStrToFat (FileName, MainNameLen, File8Dot3Name)) {
PossibleShortName = FALSE;
}
if (FatStrToFat (ExtendName, ExtendNameLen, File8Dot3Name + FAT_MAIN_NAME_LEN)) {
PossibleShortName = FALSE;
}
return PossibleShortName;
}
STATIC
UINTN
FatTrimAsciiTrailingBlanks (
IN CHAR8 *Name,
IN UINTN Len
)
/*++
Routine Description:
Trim the trailing blanks of fat name.
Arguments:
Name - The Char8 string needs to be trimed.
Len - The length of the fat name.
Returns:
The real length of the fat name after the trailing blanks are trimmed.
--*/
{
while (Len > 0 && Name[Len - 1] == ' ') {
Len--;
}
return Len;
}
VOID
FatNameToStr (
IN CHAR8 *FatName,
IN UINTN Len,
IN UINTN LowerCase,
OUT CHAR16 *Str
)
/*++
Routine Description:
Convert the ascii fat name to the unicode string and strip trailing spaces,
and if necessary, convert the unicode string to lower case.
Arguments:
FatName - The Char8 string needs to be converted.
Len - The length of the fat name.
LowerCase - Indicate whether to convert the string to lower case.
Str - The result of the convertion.
Returns:
None.
--*/
{
//
// First, trim the trailing blanks
//
Len = FatTrimAsciiTrailingBlanks (FatName, Len);
//
// Convert fat string to unicode string
//
FatFatToStr (Len, FatName, Str);
//
// If the name is to be lower cased, do it now
//
if (LowerCase != 0) {
FatStrLwr (Str);
}
}
VOID
FatCreate8Dot3Name (
IN FAT_OFILE *Parent,
IN FAT_DIRENT *DirEnt
)
/*++
Routine Description:
This function generates 8Dot3 name from user specified name for a newly created file.
Arguments:
Parent - The parent directory.
DirEnt - The directory entry whose 8Dot3Name needs to be generated.
Returns:
None.
--*/
{
CHAR8 *ShortName;
CHAR8 *ShortNameChar;
UINTN BaseTagLen;
UINTN Index;
UINTN Retry;
UINT8 Segment;
union {
UINT32 Crc;
struct HEX_DATA {
UINT8 Segment : HASH_VALUE_TAG_LEN;
} Hex[HASH_VALUE_TAG_LEN];
} HashValue;
//
// Make sure the whole directory has been loaded
//
ASSERT (Parent->ODir->EndOfDir);
ShortName = DirEnt->Entry.FileName;
//
// Trim trailing blanks of 8.3 name
//
BaseTagLen = FatTrimAsciiTrailingBlanks (ShortName, FAT_MAIN_NAME_LEN);
if (BaseTagLen > SPEC_BASE_TAG_LEN) {
BaseTagLen = SPEC_BASE_TAG_LEN;
}
//
// We first use the algorithm described by spec.
//
ShortNameChar = ShortName + BaseTagLen;
*ShortNameChar++ = '~';
*ShortNameChar = '1';
Retry = 0;
while (*FatShortNameHashSearch (Parent->ODir, ShortName) != NULL) {
*ShortNameChar = (CHAR8)(*ShortNameChar + 1);
if (++Retry == MAX_SPEC_RETRY) {
//
// We use new algorithm to generate 8.3 name
//
ASSERT (DirEnt->FileString != NULL);
gBS->CalculateCrc32 (DirEnt->FileString, StrSize (DirEnt->FileString), &HashValue.Crc);
if (BaseTagLen > HASH_BASE_TAG_LEN) {
BaseTagLen = HASH_BASE_TAG_LEN;
}
ShortNameChar = ShortName + BaseTagLen;
for (Index = 0; Index < HASH_VALUE_TAG_LEN; Index++) {
Segment = HashValue.Hex[Index].Segment;
if (Segment > 9) {
*ShortNameChar++ = (CHAR8)(Segment - 10 + 'A');
} else {
*ShortNameChar++ = (CHAR8)(Segment + '0');
}
}
*ShortNameChar++ = '~';
*ShortNameChar = '1';
}
}
}
STATIC
UINT8
FatCheckNameCase (
IN CHAR16 *Str,
IN UINT8 InCaseFlag
)
/*++
Routine Description:
Check the string is lower case or upper case
and it is used by fatname to dir entry count
Arguments:
Str - The string which needs to be checked.
InCaseFlag - The input case flag which is returned when the string is lower case.
Returns:
OutCaseFlag - The output case flag.
--*/
{
CHAR16 Buffer[FAT_MAIN_NAME_LEN + 1];
UINT8 OutCaseFlag;
ASSERT (StrSize (Str) <= sizeof (Buffer));
//
// Assume the case of input string is mixed
//
OutCaseFlag = FAT_CASE_MIXED;
//
// Lower case a copy of the string, if it matches the
// original then the string is lower case
//
StrCpy (Buffer, Str);
FatStrLwr (Buffer);
if (StrCmp (Str, Buffer) == 0) {
OutCaseFlag = InCaseFlag;
}
//
// Upper case a copy of the string, if it matches the
// original then the string is upper case
//
StrCpy (Buffer, Str);
FatStrUpr (Buffer);
if (StrCmp (Str, Buffer) == 0) {
OutCaseFlag = 0;
}
return OutCaseFlag;
}
VOID
FatSetCaseFlag (
IN FAT_DIRENT *DirEnt
)
/*++
Routine Description:
Set the caseflag value for the directory entry.
Arguments:
DirEnt - The logical directory entry whose caseflag value is to be set.
Returns:
None.
--*/
{
CHAR16 LfnBuffer[FAT_MAIN_NAME_LEN + 1 + FAT_EXTEND_NAME_LEN + 1];
CHAR16 *TempCharPtr;
CHAR16 *ExtendName;
CHAR16 *FileNameCharPtr;
UINT8 CaseFlag;
ExtendName = NULL;
TempCharPtr = LfnBuffer;
FileNameCharPtr = DirEnt->FileString;
ASSERT (StrSize (DirEnt->FileString) <= sizeof (LfnBuffer));
while ((*TempCharPtr = *FileNameCharPtr) != 0) {
if (*TempCharPtr == L'.') {
ExtendName = TempCharPtr;
}
TempCharPtr++;
FileNameCharPtr++;
}
CaseFlag = 0;
if (ExtendName != NULL) {
*ExtendName = 0;
ExtendName++;
CaseFlag = (UINT8)(CaseFlag | FatCheckNameCase (ExtendName, FAT_CASE_EXT_LOWER));
}
CaseFlag = (UINT8)(CaseFlag | FatCheckNameCase (LfnBuffer, FAT_CASE_NAME_LOWER));
if ((CaseFlag & FAT_CASE_MIXED) == 0) {
//
// We just need one directory entry to store this file name entry
//
DirEnt->Entry.CaseFlag = CaseFlag;
} else {
//
// We need one extra directory entry to store the mixed case entry
//
DirEnt->Entry.CaseFlag = 0;
DirEnt->EntryCount++;
}
}
VOID
FatGetFileNameViaCaseFlag (
IN FAT_DIRENT *DirEnt,
OUT CHAR16 *FileString
)
/*++
Routine Description:
Convert the 8.3 ASCII fat name to cased Unicode string according to case flag.
Arguments:
DirEnt - The corresponding directory entry.
FileString - The output Unicode file name.
Returns:
None.
--*/
{
UINT8 CaseFlag;
CHAR8 *File8Dot3Name;
CHAR16 TempExt[1 + FAT_EXTEND_NAME_LEN + 1];
//
// Store file extension like ".txt"
//
CaseFlag = DirEnt->Entry.CaseFlag;
File8Dot3Name = DirEnt->Entry.FileName;
FatNameToStr (File8Dot3Name, FAT_MAIN_NAME_LEN, CaseFlag & FAT_CASE_NAME_LOWER, FileString);
FatNameToStr (File8Dot3Name + FAT_MAIN_NAME_LEN, FAT_EXTEND_NAME_LEN, CaseFlag & FAT_CASE_EXT_LOWER, &TempExt[1]);
if (TempExt[1] != 0) {
TempExt[0] = L'.';
StrCat (FileString, TempExt);
}
}
UINT8
FatCheckSum (
IN CHAR8 *ShortNameString
)
/*++
Routine Description:
Get the Check sum for a short name.
Arguments:
ShortNameString - The short name for a file.
Returns:
Sum - UINT8 checksum.
--*/
{
UINTN ShortNameLen;
UINT8 Sum;
Sum = 0;
for (ShortNameLen = FAT_NAME_LEN; ShortNameLen != 0; ShortNameLen--) {
Sum = (UINT8)(((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *ShortNameString++);
}
return Sum;
}
CHAR16 *
FatGetNextNameComponent (
IN CHAR16 *Path,
OUT CHAR16 *Name
)
/*++
Routine Description:
Takes Path as input, returns the next name component
in Name, and returns the position after Name (e.g., the
start of the next name component)
Arguments:
Path - The path of one file.
Name - The next name component in Path.
Returns:
The position after Name in the Path
--*/
{
while (*Path != 0 && *Path != PATH_NAME_SEPARATOR) {
*Name++ = *Path++;
}
*Name = 0;
//
// Get off of trailing path name separator
//
while (*Path == PATH_NAME_SEPARATOR) {
Path++;
}
return Path;
}
BOOLEAN
FatFileNameIsValid (
IN CHAR16 *InputFileName,
OUT CHAR16 *OutputFileName
)
/*++
Routine Description:
Check whether the IFileName is valid long file name. If the IFileName is a valid
long file name, then we trim the possible leading blanks and leading/trailing dots.
the trimmed filename is stored in OutputFileName
Arguments:
InputFileName - The input file name.
OutputFileName - The output file name.
Returns:
TRUE - The InputFileName is a valid long file name.
FALSE - The InputFileName is not a valid long file name.
--*/
{
CHAR16 *TempNamePointer;
CHAR16 TempChar;
//
// Trim Leading blanks
//
while (*InputFileName == L' ') {
InputFileName++;
}
TempNamePointer = OutputFileName;
while (*InputFileName != 0) {
*TempNamePointer++ = *InputFileName++;
}
//
// Trim Trailing blanks and dots
//
while (TempNamePointer > OutputFileName) {
TempChar = *(TempNamePointer - 1);
if (TempChar != L' ' && TempChar != L'.') {
break;
}
TempNamePointer--;
}
*TempNamePointer = 0;
//
// Per FAT Spec the file name should meet the following criteria:
// C1. Length (FileLongName) <= 255
// C2. Length (X:FileFullPath<NUL>) <= 260
// Here we check C1.
//
if (TempNamePointer - OutputFileName > EFI_FILE_STRING_LENGTH) {
return FALSE;
}
//
// See if there is any illegal characters within the name
//
do {
if (*OutputFileName < 0x20 ||
*OutputFileName == '\"' ||
*OutputFileName == '*' ||
*OutputFileName == '/' ||
*OutputFileName == ':' ||
*OutputFileName == '<' ||
*OutputFileName == '>' ||
*OutputFileName == '?' ||
*OutputFileName == '\\' ||
*OutputFileName == '|'
) {
return FALSE;
}
OutputFileName++;
} while (*OutputFileName != 0);
return TRUE;
}

View File

@ -0,0 +1,816 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
FileSpace.c
Abstract:
Routines dealing with disk spaces and FAT table entries
Revision History
--*/
#include "Fat.h"
STATIC
VOID *
FatLoadFatEntry (
IN FAT_VOLUME *Volume,
IN UINTN Index
)
/*++
Routine Description:
Get the FAT entry of the volume, which is identified with the Index.
Arguments:
Volume - FAT file system volume.
Index - The index of the FAT entry of the volume.
Returns:
The buffer of the FAT entry
--*/
{
UINTN Pos;
EFI_STATUS Status;
if (Index > (Volume->MaxCluster + 1)) {
Volume->FatEntryBuffer = (UINT32) -1;
return &Volume->FatEntryBuffer;
}
//
// Compute buffer position needed
//
switch (Volume->FatType) {
case FAT12:
Pos = FAT_POS_FAT12 (Index);
break;
case FAT16:
Pos = FAT_POS_FAT16 (Index);
break;
default:
Pos = FAT_POS_FAT32 (Index);
}
//
// Set the position and read the buffer
//
Volume->FatEntryPos = Volume->FatPos + Pos;
Status = FatDiskIo (
Volume,
READ_FAT,
Volume->FatEntryPos,
Volume->FatEntrySize,
&Volume->FatEntryBuffer
);
if (EFI_ERROR (Status)) {
Volume->FatEntryBuffer = (UINT32) -1;
}
return &Volume->FatEntryBuffer;
}
STATIC
UINTN
FatGetFatEntry (
IN FAT_VOLUME *Volume,
IN UINTN Index
)
/*++
Routine Description:
Get the FAT entry value of the volume, which is identified with the Index.
Arguments:
Volume - FAT file system volume.
Index - The index of the FAT entry of the volume.
Returns:
The value of the FAT entry.
--*/
{
VOID *Pos;
UINT8 *E12;
UINT16 *E16;
UINT32 *E32;
UINTN Accum;
Pos = FatLoadFatEntry (Volume, Index);
if (Index > (Volume->MaxCluster + 1)) {
return (UINTN) -1;
}
switch (Volume->FatType) {
case FAT12:
E12 = Pos;
Accum = E12[0] | (E12[1] << 8);
Accum = FAT_ODD_CLUSTER_FAT12 (Index) ? (Accum >> 4) : (Accum & FAT_CLUSTER_MASK_FAT12);
Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT12) ? FAT_CLUSTER_SPECIAL_EXT : 0);
break;
case FAT16:
E16 = Pos;
Accum = *E16;
Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT16) ? FAT_CLUSTER_SPECIAL_EXT : 0);
break;
default:
E32 = Pos;
Accum = *E32 & FAT_CLUSTER_MASK_FAT32;
Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT32) ? FAT_CLUSTER_SPECIAL_EXT : 0);
}
return Accum;
}
STATIC
EFI_STATUS
FatSetFatEntry (
IN FAT_VOLUME *Volume,
IN UINTN Index,
IN UINTN Value
)
/*++
Routine Description:
Set the FAT entry value of the volume, which is identified with the Index.
Arguments:
Volume - FAT file system volume.
Index - The index of the FAT entry of the volume.
Value - The new value of the FAT entry.
Returns:
EFI_SUCCESS - Set the new FAT entry value sucessfully.
EFI_VOLUME_CORRUPTED - The FAT type of the volume is error.
other - An error occurred when operation the FAT entries.
--*/
{
VOID *Pos;
UINT8 *E12;
UINT16 *E16;
UINT32 *E32;
UINTN Accum;
EFI_STATUS Status;
UINTN OriginalVal;
if (Index < FAT_MIN_CLUSTER) {
return EFI_VOLUME_CORRUPTED;
}
OriginalVal = FatGetFatEntry (Volume, Index);
if (Value == FAT_CLUSTER_FREE && OriginalVal != FAT_CLUSTER_FREE) {
Volume->FatInfoSector.FreeInfo.ClusterCount += 1;
if (Index < Volume->FatInfoSector.FreeInfo.NextCluster) {
Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;
}
} else if (Value != FAT_CLUSTER_FREE && OriginalVal == FAT_CLUSTER_FREE) {
if (Volume->FatInfoSector.FreeInfo.ClusterCount != 0) {
Volume->FatInfoSector.FreeInfo.ClusterCount -= 1;
}
}
//
// Make sure the entry is in memory
//
Pos = FatLoadFatEntry (Volume, Index);
//
// Update the value
//
switch (Volume->FatType) {
case FAT12:
E12 = Pos;
Accum = E12[0] | (E12[1] << 8);
Value = Value & FAT_CLUSTER_MASK_FAT12;
if (FAT_ODD_CLUSTER_FAT12 (Index)) {
Accum = (Value << 4) | (Accum & 0xF);
} else {
Accum = Value | (Accum & FAT_CLUSTER_UNMASK_FAT12);
}
E12[0] = (UINT8) (Accum & 0xFF);
E12[1] = (UINT8) (Accum >> 8);
break;
case FAT16:
E16 = Pos;
*E16 = (UINT16) Value;
break;
default:
E32 = Pos;
*E32 = (*E32 & FAT_CLUSTER_UNMASK_FAT32) | (UINT32) (Value & FAT_CLUSTER_MASK_FAT32);
}
//
// If the volume's dirty bit is not set, set it now
//
if (!Volume->FatDirty && Volume->FatType != FAT12) {
Volume->FatDirty = TRUE;
FatAccessVolumeDirty (Volume, WRITE_FAT, &Volume->DirtyValue);
}
//
// Write the updated fat entry value to the volume
// The fat is the first fat, and other fat will be in sync
// when the FAT cache flush back.
//
Status = FatDiskIo (
Volume,
WRITE_FAT,
Volume->FatEntryPos,
Volume->FatEntrySize,
&Volume->FatEntryBuffer
);
return Status;
}
STATIC
EFI_STATUS
FatFreeClusters (
IN FAT_VOLUME *Volume,
IN UINTN Cluster
)
/*++
Routine Description:
Free the cluster clain.
Arguments:
Volume - FAT file system volume.
Cluster - The first cluster of cluster chain.
Returns:
EFI_SUCCESS - The cluster chain is freed successfully.
EFI_VOLUME_CORRUPTED - There are errors in the file's clusters.
--*/
{
UINTN LastCluster;
while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatShrinkEof: cluster chain corrupt\n"));
return EFI_VOLUME_CORRUPTED;
}
LastCluster = Cluster;
Cluster = FatGetFatEntry (Volume, Cluster);
FatSetFatEntry (Volume, LastCluster, FAT_CLUSTER_FREE);
}
return EFI_SUCCESS;
}
STATIC
UINTN
FatAllocateCluster (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Allocate a free cluster and return the cluster index.
Arguments:
Volume - FAT file system volume.
Returns:
The index of the free cluster
--*/
{
UINTN Cluster;
//
// Start looking at FatFreePos for the next unallocated cluster
//
if (Volume->DiskError) {
return (UINTN) FAT_CLUSTER_LAST;
}
for (;;) {
//
// If the end of the list, return no available cluster
//
if (Volume->FatInfoSector.FreeInfo.NextCluster > (Volume->MaxCluster + 1)) {
if (Volume->FreeInfoValid && 0 < (INT32) (Volume->FatInfoSector.FreeInfo.ClusterCount)) {
Volume->FreeInfoValid = FALSE;
}
FatComputeFreeInfo (Volume);
if (Volume->FatInfoSector.FreeInfo.NextCluster > (Volume->MaxCluster + 1)) {
return (UINTN) FAT_CLUSTER_LAST;
}
}
Cluster = FatGetFatEntry (Volume, Volume->FatInfoSector.FreeInfo.NextCluster);
if (Cluster == FAT_CLUSTER_FREE) {
break;
}
//
// Try the next cluster
//
Volume->FatInfoSector.FreeInfo.NextCluster += 1;
}
Cluster = Volume->FatInfoSector.FreeInfo.NextCluster;
Volume->FatInfoSector.FreeInfo.NextCluster += 1;
return Cluster;
}
STATIC
UINTN
FatSizeToClusters (
IN FAT_VOLUME *Volume,
IN UINTN Size
)
/*++
Routine Description:
Count the number of clusters given a size
Arguments:
Volume - The file system volume.
Size - The size in bytes.
Returns:
The number of the clusters.
--*/
{
UINTN Clusters;
Clusters = Size >> Volume->ClusterAlignment;
if ((Size & (Volume->ClusterSize - 1)) > 0) {
Clusters += 1;
}
return Clusters;
}
EFI_STATUS
FatShrinkEof (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Shrink the end of the open file base on the file size.
Arguments:
OFile - The open file.
Returns:
EFI_SUCCESS - Shrinked sucessfully.
EFI_VOLUME_CORRUPTED - There are errors in the file's clusters.
--*/
{
FAT_VOLUME *Volume;
UINTN NewSize;
UINTN CurSize;
UINTN Cluster;
UINTN LastCluster;
Volume = OFile->Volume;
ASSERT_VOLUME_LOCKED (Volume);
NewSize = FatSizeToClusters (Volume, OFile->FileSize);
//
// Find the address of the last cluster
//
Cluster = OFile->FileCluster;
LastCluster = FAT_CLUSTER_FREE;
if (NewSize != 0) {
for (CurSize = 0; CurSize < NewSize; CurSize++) {
if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatShrinkEof: cluster chain corrupt\n"));
return EFI_VOLUME_CORRUPTED;
}
LastCluster = Cluster;
Cluster = FatGetFatEntry (Volume, Cluster);
}
FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
} else {
//
// Check to see if the file is already completely truncated
//
if (Cluster == FAT_CLUSTER_FREE) {
return EFI_SUCCESS;
}
//
// The file is being completely truncated.
//
OFile->FileCluster = FAT_CLUSTER_FREE;
}
//
// Set CurrentCluster == FileCluster
// to force a recalculation of Position related stuffs
//
OFile->FileCurrentCluster = OFile->FileCluster;
OFile->FileLastCluster = LastCluster;
OFile->Dirty = TRUE;
//
// Free the remaining cluster chain
//
return FatFreeClusters (Volume, Cluster);
}
EFI_STATUS
FatGrowEof (
IN FAT_OFILE *OFile,
IN UINT64 NewSizeInBytes
)
/*++
Routine Description:
Grow the end of the open file base on the NewSizeInBytes.
Arguments:
OFile - The open file.
NewSizeInBytes - The new size in bytes of the open file.
Returns:
EFI_SUCCESS - The file is grown sucessfully.
EFI_UNSUPPORTED - The file size is larger than 4GB.
EFI_VOLUME_CORRUPTED - There are errors in the files' clusters.
EFI_VOLUME_FULL - The volume is full and can not grow the file.
--*/
{
FAT_VOLUME *Volume;
EFI_STATUS Status;
UINTN Cluster;
UINTN CurSize;
UINTN NewSize;
UINTN LastCluster;
UINTN NewCluster;
UINTN ClusterCount;
//
// For FAT file system, the max file is 4GB.
//
if (NewSizeInBytes > 0x0FFFFFFFFL) {
return EFI_UNSUPPORTED;
}
Volume = OFile->Volume;
ASSERT_VOLUME_LOCKED (Volume);
//
// If the file is already large enough, do nothing
//
CurSize = FatSizeToClusters (Volume, OFile->FileSize);
NewSize = FatSizeToClusters (Volume, (UINTN) NewSizeInBytes);
if (CurSize < NewSize) {
//
// If we haven't found the files last cluster do it now
//
if ((OFile->FileCluster != 0) && (OFile->FileLastCluster == 0)) {
Cluster = OFile->FileCluster;
ClusterCount = 0;
while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
DEBUG (
(EFI_D_INIT | EFI_D_ERROR,
"FatGrowEof: cluster chain corrupt\n")
);
Status = EFI_VOLUME_CORRUPTED;
goto Done;
}
ClusterCount++;
OFile->FileLastCluster = Cluster;
Cluster = FatGetFatEntry (Volume, Cluster);
}
if (ClusterCount != CurSize) {
DEBUG (
(EFI_D_INIT | EFI_D_ERROR,
"FatGrowEof: cluster chain size does not match file size\n")
);
Status = EFI_VOLUME_CORRUPTED;
goto Done;
}
}
//
// Loop until we've allocated enough space
//
LastCluster = OFile->FileLastCluster;
while (CurSize < NewSize) {
NewCluster = FatAllocateCluster (Volume);
if (FAT_END_OF_FAT_CHAIN (NewCluster)) {
if (LastCluster != FAT_CLUSTER_FREE) {
FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
OFile->FileLastCluster = LastCluster;
}
Status = EFI_VOLUME_FULL;
goto Done;
}
if (LastCluster != 0) {
FatSetFatEntry (Volume, LastCluster, NewCluster);
} else {
OFile->FileCluster = NewCluster;
OFile->FileCurrentCluster = NewCluster;
}
LastCluster = NewCluster;
CurSize += 1;
}
//
// Terminate the cluster list
//
FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
OFile->FileLastCluster = LastCluster;
}
OFile->FileSize = (UINTN) NewSizeInBytes;
OFile->Dirty = TRUE;
return EFI_SUCCESS;
Done:
FatShrinkEof (OFile);
return Status;
}
EFI_STATUS
FatOFilePosition (
IN FAT_OFILE *OFile,
IN UINTN Position,
IN UINTN PosLimit
)
/*++
Routine Description:
Seek OFile to requested position, and calculate the number of
consecutive clusters from the position in the file
Arguments:
OFile - The open file.
Position - The file's position which will be accessed.
PosLimit - The maximum length current reading/writing may access
Returns:
EFI_SUCCESS - Set the info successfully.
EFI_VOLUME_CORRUPTED - Cluster chain corrupt.
--*/
{
FAT_VOLUME *Volume;
UINTN ClusterSize;
UINTN Cluster;
UINTN StartPos;
UINTN Run;
Volume = OFile->Volume;
ClusterSize = Volume->ClusterSize;
ASSERT_VOLUME_LOCKED (Volume);
//
// If this is the fixed root dir, then compute it's position
// from it's fixed info in the fat bpb
//
if (OFile->IsFixedRootDir) {
OFile->PosDisk = Volume->RootPos + Position;
Run = OFile->FileSize - Position;
} else {
//
// Run the file's cluster chain to find the current position
// If possible, run from the current cluster rather than
// start from beginning
// Assumption: OFile->Position is always consistent with
// OFile->FileCurrentCluster.
// OFile->Position is not modified outside this function;
// OFile->FileCurrentCluster is modified outside this function
// to be the same as OFile->FileCluster
// when OFile->FileCluster is updated, so make a check of this
// and invalidate the original OFile->Position in this case
//
Cluster = OFile->FileCurrentCluster;
StartPos = OFile->Position;
if (Position < StartPos || OFile->FileCluster == Cluster) {
StartPos = 0;
Cluster = OFile->FileCluster;
}
while (StartPos + ClusterSize <= Position) {
StartPos += ClusterSize;
if (Cluster == FAT_CLUSTER_FREE || (Cluster >= FAT_CLUSTER_SPECIAL)) {
DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatOFilePosition:"" cluster chain corrupt\n"));
return EFI_VOLUME_CORRUPTED;
}
Cluster = FatGetFatEntry (Volume, Cluster);
}
if (Cluster < FAT_MIN_CLUSTER) {
return EFI_VOLUME_CORRUPTED;
}
OFile->PosDisk = Volume->FirstClusterPos +
LShiftU64 (Cluster - FAT_MIN_CLUSTER, Volume->ClusterAlignment) +
Position - StartPos;
OFile->FileCurrentCluster = Cluster;
OFile->Position = StartPos;
//
// Compute the number of consecutive clusters in the file
//
Run = StartPos + ClusterSize - Position;
if (!FAT_END_OF_FAT_CHAIN (Cluster)) {
while ((FatGetFatEntry (Volume, Cluster) == Cluster + 1) && Run < PosLimit) {
Run += ClusterSize;
Cluster += 1;
}
}
}
OFile->PosRem = Run;
return EFI_SUCCESS;
}
UINTN
FatPhysicalDirSize (
IN FAT_VOLUME *Volume,
IN UINTN Cluster
)
/*++
Routine Description:
Get the size of directory of the open file
Arguments:
Volume - The File System Volume.
Cluster - The Starting cluster.
Returns:
The physical size of the file starting at the input cluster, if there is error in the
cluster chain, the return value is 0.
--*/
{
UINTN Size;
ASSERT_VOLUME_LOCKED (Volume);
//
// Run the cluster chain for the OFile
//
Size = 0;
//
// N.B. ".." directories on some media do not contain a starting
// cluster. In the case of "." or ".." we don't need the size anyway.
//
if (Cluster != 0) {
while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
DEBUG (
(EFI_D_INIT | EFI_D_ERROR,
"FATDirSize: cluster chain corrupt\n")
);
return 0;
}
Size += Volume->ClusterSize;
Cluster = FatGetFatEntry (Volume, Cluster);
}
}
return Size;
}
UINT64
FatPhysicalFileSize (
IN FAT_VOLUME *Volume,
IN UINTN RealSize
)
/*++
Routine Description:
Get the physical size of a file on the disk.
Arguments:
Volume - The file system volume.
RealSize - The real size of a file.
Returns:
The physical size of a file on the disk.
--*/
{
UINTN ClusterSizeMask;
UINT64 PhysicalSize;
ClusterSizeMask = Volume->ClusterSize - 1;
PhysicalSize = (RealSize + ClusterSizeMask) & (~((UINT64) ClusterSizeMask));
return PhysicalSize;
}
VOID
FatComputeFreeInfo (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Update the free cluster info of FatInfoSector of the volume.
Arguments:
Volume - FAT file system volume.
Returns:
None.
--*/
{
UINTN Index;
//
// If we don't have valid info, compute it now
//
if (!Volume->FreeInfoValid) {
Volume->FreeInfoValid = TRUE;
Volume->FatInfoSector.FreeInfo.ClusterCount = 0;
for (Index = Volume->MaxCluster + 1; Index >= FAT_MIN_CLUSTER; Index--) {
if (Volume->DiskError) {
break;
}
if (FatGetFatEntry (Volume, Index) == FAT_CLUSTER_FREE) {
Volume->FatInfoSector.FreeInfo.ClusterCount += 1;
Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;
}
}
Volume->FatInfoSector.Signature = FAT_INFO_SIGNATURE;
Volume->FatInfoSector.InfoBeginSignature = FAT_INFO_BEGIN_SIGNATURE;
Volume->FatInfoSector.InfoEndSignature = FAT_INFO_END_SIGNATURE;
}
}

View File

@ -0,0 +1,480 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
flush.c
Abstract:
Routines that check references and flush OFiles
Revision History
--*/
#include "Fat.h"
EFI_STATUS
EFIAPI
FatFlush (
IN EFI_FILE *FHand
)
/*++
Routine Description:
Flushes all data associated with the file handle.
Arguments:
FHand - Handle to file to flush.
Returns:
EFI_SUCCESS - Flushed the file successfully.
EFI_WRITE_PROTECTED - The volume is read only.
EFI_ACCESS_DENIED - The file is read only.
Others - Flushing of the file failed.
--*/
{
FAT_IFILE *IFile;
FAT_OFILE *OFile;
FAT_VOLUME *Volume;
EFI_STATUS Status;
IFile = IFILE_FROM_FHAND (FHand);
OFile = IFile->OFile;
Volume = OFile->Volume;
//
// If the file has a permanent error, return it
//
if (EFI_ERROR (OFile->Error)) {
return OFile->Error;
}
if (Volume->ReadOnly) {
return EFI_WRITE_PROTECTED;
}
//
// If read only, return error
//
if (IFile->ReadOnly) {
return EFI_ACCESS_DENIED;
}
//
// Flush the OFile
//
FatAcquireLock ();
Status = FatOFileFlush (OFile);
Status = FatCleanupVolume (OFile->Volume, OFile, Status);
FatReleaseLock ();
return Status;
}
EFI_STATUS
EFIAPI
FatClose (
IN EFI_FILE *FHand
)
/*++
Routine Description:
Flushes & Closes the file handle.
Arguments:
FHand - Handle to the file to delete.
Returns:
EFI_SUCCESS - Closed the file successfully.
--*/
{
FAT_IFILE *IFile;
FAT_OFILE *OFile;
FAT_VOLUME *Volume;
IFile = IFILE_FROM_FHAND (FHand);
OFile = IFile->OFile;
Volume = OFile->Volume;
//
// Lock the volume
//
FatAcquireLock ();
//
// Close the file instance handle
//
FatIFileClose (IFile);
//
// Done. Unlock the volume
//
FatCleanupVolume (Volume, OFile, EFI_SUCCESS);
FatReleaseLock ();
//
// Close always succeed
//
return EFI_SUCCESS;
}
EFI_STATUS
FatIFileClose (
FAT_IFILE *IFile
)
/*++
Routine Description:
Close the open file instance.
Arguments:
IFile - Open file instance.
Returns:
EFI_SUCCESS - Closed the file successfully.
--*/
{
FAT_OFILE *OFile;
FAT_VOLUME *Volume;
OFile = IFile->OFile;
Volume = OFile->Volume;
ASSERT_VOLUME_LOCKED (Volume);
//
// Remove the IFile struct
//
RemoveEntryList (&IFile->Link);
//
// Add the OFile to the check reference list
//
if (OFile->CheckLink.ForwardLink == NULL) {
InsertHeadList (&Volume->CheckRef, &OFile->CheckLink);
}
//
// Done. Free the open instance structure
//
FreePool (IFile);
return EFI_SUCCESS;
}
EFI_STATUS
FatOFileFlush (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Flush the data associated with an open file.
In this implementation, only last Mod/Access time is updated.
Arguments:
OFile - The open file.
Returns:
EFI_SUCCESS - The OFile is flushed successfully.
Others - An error occurred when flushing this OFile.
--*/
{
EFI_STATUS Status;
FAT_OFILE *Parent;
FAT_DIRENT *DirEnt;
FAT_DATE_TIME FatNow;
//
// Flush each entry up the tree while dirty
//
do {
//
// If the file has a permanant error, then don't write any
// of its data to the device (may be from different media)
//
if (EFI_ERROR (OFile->Error)) {
return OFile->Error;
}
Parent = OFile->Parent;
DirEnt = OFile->DirEnt;
if (OFile->Dirty) {
//
// Update the last modification time
//
FatGetCurrentFatTime (&FatNow);
CopyMem (&DirEnt->Entry.FileLastAccess, &FatNow.Date, sizeof (FAT_DATE));
if (!OFile->PreserveLastModification) {
FatGetCurrentFatTime (&DirEnt->Entry.FileModificationTime);
}
OFile->PreserveLastModification = FALSE;
if (OFile->Archive) {
DirEnt->Entry.Attributes |= FAT_ATTRIBUTE_ARCHIVE;
OFile->Archive = FALSE;
}
//
// Write the directory entry
//
if (Parent != NULL && !DirEnt->Invalid) {
//
// Write the OFile's directory entry
//
Status = FatStoreDirEnt (Parent, DirEnt);
if (EFI_ERROR (Status)) {
return Status;
}
}
OFile->Dirty = FALSE;
}
//
// Check the parent
//
OFile = Parent;
} while (OFile != NULL);
return EFI_SUCCESS;
}
BOOLEAN
FatCheckOFileRef (
IN FAT_OFILE *OFile
)
/*++
Routine Description:
Check the references of the OFile.
If the OFile (that is checked) is no longer
referenced, then it is freed.
Arguments:
OFile - The OFile to be checked.
Returns:
TRUE - The OFile is not referenced and freed.
FALSE - The OFile is kept.
--*/
{
//
// If the OFile is on the check ref list, remove it
//
if (OFile->CheckLink.ForwardLink != NULL) {
RemoveEntryList (&OFile->CheckLink);
OFile->CheckLink.ForwardLink = NULL;
}
FatOFileFlush (OFile);
//
// Are there any references to this OFile?
//
if (!IsListEmpty (&OFile->Opens) || !IsListEmpty (&OFile->ChildHead)) {
//
// The OFile cannot be freed
//
return FALSE;
}
//
// Free the Ofile
//
FatCloseDirEnt (OFile->DirEnt);
return TRUE;
}
STATIC
VOID
FatCheckVolumeRef (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Check the references of all open files on the volume.
Any open file (that is checked) that is no longer
referenced, is freed - and it's parent open file
is then referenced checked.
Arguments:
Volume - The volume to check the pending open file list.
Returns:
None
--*/
{
FAT_OFILE *OFile;
FAT_OFILE *Parent;
//
// Check all files on the pending check list
//
while (!IsListEmpty (&Volume->CheckRef)) {
//
// Start with the first file listed
//
Parent = OFILE_FROM_CHECKLINK (Volume->CheckRef.ForwardLink);
//
// Go up the tree cleaning up any un-referenced OFiles
//
while (Parent != NULL) {
OFile = Parent;
Parent = OFile->Parent;
if (!FatCheckOFileRef (OFile)) {
break;
}
}
}
}
EFI_STATUS
FatCleanupVolume (
IN FAT_VOLUME *Volume,
IN FAT_OFILE *OFile,
IN EFI_STATUS EfiStatus
)
/*++
Routine Description:
Set error status for a specific OFile, reference checking the volume.
If volume is already marked as invalid, and all resources are freed
after reference checking, the file system protocol is uninstalled and
the volume structure is freed.
Arguments:
Volume - the Volume that is to be reference checked and unlocked.
OFile - the OFile whose permanent error code is to be set.
EfiStatus - error code to be set.
Returns:
EFI_SUCCESS - Clean up the volume successfully.
Others - Cleaning up of the volume is failed.
--*/
{
EFI_STATUS Status;
//
// Flag the OFile
//
if (OFile != NULL) {
FatSetVolumeError (OFile, EfiStatus);
}
//
// Clean up any dangling OFiles that don't have IFiles
// we don't check return status here because we want the
// volume be cleaned up even the volume is invalid.
//
FatCheckVolumeRef (Volume);
if (Volume->Valid) {
//
// Update the free hint info. Volume->FreeInfoPos != 0
// indicates this a FAT32 volume
//
if (Volume->FreeInfoValid && Volume->FatDirty && Volume->FreeInfoPos) {
Status = FatDiskIo (Volume, WRITE_DISK, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Update that the volume is not dirty
//
if (Volume->FatDirty && Volume->FatType != FAT12) {
Volume->FatDirty = FALSE;
Status = FatAccessVolumeDirty (Volume, WRITE_FAT, &Volume->NotDirtyValue);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// Flush all dirty cache entries to disk
//
Status = FatVolumeFlushCache (Volume);
if (EFI_ERROR (Status)) {
return Status;
}
}
//
// If the volume is cleared , remove it.
// The only time volume be invalidated is in DriverBindingStop.
//
if (Volume->Root == NULL && !Volume->Valid) {
//
// Free the volume structure
//
FatFreeVolume (Volume);
}
return EfiStatus;
}
VOID
FatSetVolumeError (
IN FAT_OFILE *OFile,
IN EFI_STATUS Status
)
/*++
Routine Description:
Set the OFile and its child OFile with the error Status
Arguments:
OFile - The OFile whose permanent error code is to be set.
Status - Error code to be set.
Returns:
None
--*/
{
LIST_ENTRY *Link;
FAT_OFILE *ChildOFile;
//
// If this OFile doesn't already have an error, set one
//
if (!EFI_ERROR (OFile->Error)) {
OFile->Error = Status;
}
//
// Set the error on each child OFile
//
for (Link = OFile->ChildHead.ForwardLink; Link != &OFile->ChildHead; Link = Link->ForwardLink) {
ChildOFile = OFILE_FROM_CHILDLINK (Link);
FatSetVolumeError (ChildOFile, Status);
}
}

View File

@ -0,0 +1,217 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Hash.c
Abstract:
Hash table operations
Revision History
--*/
#include "Fat.h"
STATIC
UINT32
FatHashLongName (
IN CHAR16 *LongNameString
)
/*++
Routine Description:
Get hash value for long name.
Arguments:
LongNameString - The long name string to be hashed.
Returns:
HashValue.
--*/
{
UINT32 HashValue;
CHAR16 UpCasedLongFileName[EFI_PATH_STRING_LENGTH];
StrCpy (UpCasedLongFileName, LongNameString);
FatStrUpr (UpCasedLongFileName);
gBS->CalculateCrc32 (UpCasedLongFileName, StrSize (UpCasedLongFileName), &HashValue);
return (HashValue & HASH_TABLE_MASK);
}
STATIC
UINT32
FatHashShortName (
IN CHAR8 *ShortNameString
)
/*++
Routine Description:
Get hash value for short name.
Arguments:
ShortNameString - The short name string to be hashed.
Returns:
HashValue
--*/
{
UINT32 HashValue;
gBS->CalculateCrc32 (ShortNameString, FAT_NAME_LEN, &HashValue);
return (HashValue & HASH_TABLE_MASK);
}
FAT_DIRENT **
FatLongNameHashSearch (
IN FAT_ODIR *ODir,
IN CHAR16 *LongNameString
)
/*++
Routine Description:
Search the long name hash table for the directory entry.
Arguments:
ODir - The directory to be searched.
LongNameString - The long name string to search.
Returns:
The previous long name hash node of the directory entry.
--*/
{
FAT_DIRENT **PreviousHashNode;
for (PreviousHashNode = &ODir->LongNameHashTable[FatHashLongName (LongNameString)];
*PreviousHashNode != NULL;
PreviousHashNode = &(*PreviousHashNode)->LongNameForwardLink
) {
if (FatStriCmp (LongNameString, (*PreviousHashNode)->FileString) == 0) {
break;
}
}
return PreviousHashNode;
}
FAT_DIRENT **
FatShortNameHashSearch (
IN FAT_ODIR *ODir,
IN CHAR8 *ShortNameString
)
/*++
Routine Description:
Search the short name hash table for the directory entry.
Arguments:
ODir - The directory to be searched.
ShortNameString - The short name string to search.
Returns:
The previous short name hash node of the directory entry.
--*/
{
FAT_DIRENT **PreviousHashNode;
for (PreviousHashNode = &ODir->ShortNameHashTable[FatHashShortName (ShortNameString)];
*PreviousHashNode != NULL;
PreviousHashNode = &(*PreviousHashNode)->ShortNameForwardLink
) {
if (CompareMem (ShortNameString, (*PreviousHashNode)->Entry.FileName, FAT_NAME_LEN) == 0) {
break;
}
}
return PreviousHashNode;
}
VOID
FatInsertToHashTable (
IN FAT_ODIR *ODir,
IN FAT_DIRENT *DirEnt
)
/*++
Routine Description:
Insert directory entry to hash table.
Arguments:
ODir - The parent directory.
DirEnt - The directory entry node.
Returns:
None.
--*/
{
FAT_DIRENT **HashTable;
UINT32 HashTableIndex;
//
// Insert hash table index for short name
//
HashTableIndex = FatHashShortName (DirEnt->Entry.FileName);
HashTable = ODir->ShortNameHashTable;
DirEnt->ShortNameForwardLink = HashTable[HashTableIndex];
HashTable[HashTableIndex] = DirEnt;
//
// Insert hash table index for long name
//
HashTableIndex = FatHashLongName (DirEnt->FileString);
HashTable = ODir->LongNameHashTable;
DirEnt->LongNameForwardLink = HashTable[HashTableIndex];
HashTable[HashTableIndex] = DirEnt;
}
VOID
FatDeleteFromHashTable (
IN FAT_ODIR *ODir,
IN FAT_DIRENT *DirEnt
)
/*++
Routine Description:
Delete directory entry from hash table.
Arguments:
ODir - The parent directory.
DirEnt - The directory entry node.
Returns:
None.
--*/
{
*FatShortNameHashSearch (ODir, DirEnt->Entry.FileName) = DirEnt->ShortNameForwardLink;
*FatLongNameHashSearch (ODir, DirEnt->FileString) = DirEnt->LongNameForwardLink;
}

View File

@ -0,0 +1,625 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Info.c
Abstract:
Routines dealing with setting/getting file/volume info
Revision History
--*/
#include "Fat.h"
EFI_STATUS
FatGetVolumeInfo (
IN FAT_VOLUME *Volume,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFI_STATUS
FatSetVolumeInfo (
IN FAT_VOLUME *Volume,
IN OUT UINTN BufferSize,
OUT VOID *Buffer
);
EFI_STATUS
FatSetOrGetInfo (
IN BOOLEAN IsSet,
IN EFI_FILE *FHand,
IN EFI_GUID *Type,
IN OUT UINTN *BufferSize,
IN OUT VOID *Buffer
);
EFI_STATUS
FatGetFileInfo (
IN FAT_OFILE *OFile,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Get the open file's info into Buffer.
Arguments:
OFile - The open file.
BufferSize - Size of Buffer.
Buffer - Buffer containing file info.
Returns:
EFI_SUCCESS - Get the file info successfully.
EFI_BUFFER_TOO_SMALL - The buffer is too small.
--*/
{
return FatGetDirEntInfo (OFile->Volume, OFile->DirEnt, BufferSize, Buffer);
}
EFI_STATUS
FatGetVolumeInfo (
IN FAT_VOLUME *Volume,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Get the volume's info into Buffer.
Arguments:
Volume - FAT file system volume.
BufferSize - Size of Buffer.
Buffer - Buffer containing volume info.
Returns:
EFI_SUCCESS - Get the volume info successfully.
EFI_BUFFER_TOO_SMALL - The buffer is too small.
--*/
{
UINTN Size;
UINTN NameSize;
UINTN ResultSize;
CHAR16 Name[FAT_NAME_LEN + 1];
EFI_STATUS Status;
EFI_FILE_SYSTEM_INFO *Info;
UINT8 ClusterAlignment;
Size = SIZE_OF_EFI_FILE_SYSTEM_INFO;
Status = FatGetVolumeEntry (Volume, Name);
NameSize = StrSize (Name);
ResultSize = Size + NameSize;
ClusterAlignment = Volume->ClusterAlignment;
//
// If we don't have valid info, compute it now
//
FatComputeFreeInfo (Volume);
Status = EFI_BUFFER_TOO_SMALL;
if (*BufferSize >= ResultSize) {
Status = EFI_SUCCESS;
Info = Buffer;
ZeroMem (Info, SIZE_OF_EFI_FILE_SYSTEM_INFO);
Info->Size = ResultSize;
Info->ReadOnly = Volume->ReadOnly;
Info->BlockSize = (UINT32) Volume->ClusterSize;
Info->VolumeSize = LShiftU64 (Volume->MaxCluster, ClusterAlignment);
Info->FreeSpace = LShiftU64 (
Volume->FatInfoSector.FreeInfo.ClusterCount,
ClusterAlignment
);
CopyMem ((CHAR8 *) Buffer + Size, Name, NameSize);
}
*BufferSize = ResultSize;
return Status;
}
EFI_STATUS
FatGetVolumeLabelInfo (
IN FAT_VOLUME *Volume,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Get the volume's label info into Buffer.
Arguments:
Volume - FAT file system volume.
BufferSize - Size of Buffer.
Buffer - Buffer containing volume's label info.
Returns:
EFI_SUCCESS - Get the volume's label info successfully.
EFI_BUFFER_TOO_SMALL - The buffer is too small.
--*/
{
UINTN Size;
UINTN NameSize;
UINTN ResultSize;
CHAR16 Name[FAT_NAME_LEN + 1];
EFI_STATUS Status;
Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO;
Status = FatGetVolumeEntry (Volume, Name);
NameSize = StrSize (Name);
ResultSize = Size + NameSize;
Status = EFI_BUFFER_TOO_SMALL;
if (*BufferSize >= ResultSize) {
Status = EFI_SUCCESS;
CopyMem ((CHAR8 *) Buffer + Size, Name, NameSize);
}
*BufferSize = ResultSize;
return Status;
}
EFI_STATUS
FatSetVolumeInfo (
IN FAT_VOLUME *Volume,
IN UINTN BufferSize,
IN VOID *Buffer
)
/*++
Routine Description:
Set the volume's info.
Arguments:
Volume - FAT file system volume.
BufferSize - Size of Buffer.
Buffer - Buffer containing the new volume info.
Returns:
EFI_SUCCESS - Set the volume info successfully.
EFI_BAD_BUFFER_SIZE - The buffer size is error.
EFI_WRITE_PROTECTED - The volume is read only.
other - An error occurred when operation the disk.
--*/
{
EFI_FILE_SYSTEM_INFO *Info;
Info = (EFI_FILE_SYSTEM_INFO *) Buffer;
if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + 2 || Info->Size > BufferSize) {
return EFI_BAD_BUFFER_SIZE;
}
return FatSetVolumeEntry (Volume, Info->VolumeLabel);
}
EFI_STATUS
FatSetVolumeLabelInfo (
IN FAT_VOLUME *Volume,
IN UINTN BufferSize,
IN VOID *Buffer
)
/*++
Routine Description:
Set the volume's label info
Arguments:
Volume - FAT file system volume.
BufferSize - Size of Buffer.
Buffer - Buffer containing the new volume label info.
Returns:
EFI_SUCCESS - Set the volume label info successfully.
EFI_WRITE_PROTECTED - The disk is write protected.
EFI_BAD_BUFFER_SIZE - The buffer size is error.
other - An error occurred when operation the disk.
--*/
{
EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info;
Info = (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *) Buffer;
if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 2) {
return EFI_BAD_BUFFER_SIZE;
}
return FatSetVolumeEntry (Volume, Info->VolumeLabel);
}
EFI_STATUS
FatSetFileInfo (
IN FAT_VOLUME *Volume,
IN FAT_IFILE *IFile,
IN FAT_OFILE *OFile,
IN UINTN BufferSize,
IN VOID *Buffer
)
/*++
Routine Description:
Set the file info.
Arguments:
Volume - FAT file system volume.
IFile - The instance of the open file.
OFile - The open file.
BufferSize - Size of Buffer.
Buffer - Buffer containing the new file info.
Returns:
EFI_SUCCESS - Set the file info successfully.
EFI_ACCESS_DENIED - It is the root directory
or the directory attribute bit can not change
or try to change a directory size
or something else.
EFI_UNSUPPORTED - The new file size is larger than 4GB.
EFI_WRITE_PROTECTED - The disk is write protected.
EFI_BAD_BUFFER_SIZE - The buffer size is error.
EFI_INVALID_PARAMETER - The time info or attributes info is error.
EFI_OUT_OF_RESOURCES - Can not allocate new memory.
EFI_VOLUME_CORRUPTED - The volume is corrupted.
other - An error occurred when operation the disk.
--*/
{
EFI_STATUS Status;
EFI_FILE_INFO *NewInfo;
FAT_OFILE *DotOFile;
FAT_OFILE *Parent;
CHAR16 NewFileName[EFI_PATH_STRING_LENGTH];
EFI_TIME ZeroTime;
FAT_DIRENT *DirEnt;
FAT_DIRENT *TempDirEnt;
UINT8 NewAttribute;
BOOLEAN ReadOnly;
ZeroMem (&ZeroTime, sizeof (EFI_TIME));
Parent = OFile->Parent;
DirEnt = OFile->DirEnt;
//
// If this is the root directory, we can't make any updates
//
if (Parent == NULL) {
return EFI_ACCESS_DENIED;
}
//
// Make sure there's a valid input buffer
//
NewInfo = Buffer;
if (BufferSize < SIZE_OF_EFI_FILE_INFO + 2 || NewInfo->Size > BufferSize) {
return EFI_BAD_BUFFER_SIZE;
}
ReadOnly = (BOOLEAN)(IFile->ReadOnly || (DirEnt->Entry.Attributes & EFI_FILE_READ_ONLY));
//
// if a zero time is specified, then the original time is preserved
//
if (CompareMem (&ZeroTime, &NewInfo->CreateTime, sizeof (EFI_TIME)) != 0) {
if (!FatIsValidTime (&NewInfo->CreateTime)) {
return EFI_INVALID_PARAMETER;
}
if (!ReadOnly) {
FatEfiTimeToFatTime (&NewInfo->CreateTime, &DirEnt->Entry.FileCreateTime);
}
}
if (CompareMem (&ZeroTime, &NewInfo->ModificationTime, sizeof (EFI_TIME)) != 0) {
if (!FatIsValidTime (&NewInfo->ModificationTime)) {
return EFI_INVALID_PARAMETER;
}
if (!ReadOnly) {
FatEfiTimeToFatTime (&NewInfo->ModificationTime, &DirEnt->Entry.FileModificationTime);
}
OFile->PreserveLastModification = TRUE;
}
if (NewInfo->Attribute & (~EFI_FILE_VALID_ATTR)) {
return EFI_INVALID_PARAMETER;
}
NewAttribute = (UINT8) NewInfo->Attribute;
//
// Can not change the directory attribute bit
//
if ((NewAttribute ^ DirEnt->Entry.Attributes) & EFI_FILE_DIRECTORY) {
return EFI_ACCESS_DENIED;
}
//
// Set the current attributes even if the IFile->ReadOnly is TRUE
//
DirEnt->Entry.Attributes = (UINT8) ((DirEnt->Entry.Attributes &~EFI_FILE_VALID_ATTR) | NewAttribute);
//
// Open the filename and see if it refers to an existing file
//
Status = FatLocateOFile (&Parent, NewInfo->FileName, DirEnt->Entry.Attributes, NewFileName);
if (EFI_ERROR (Status)) {
return Status;
}
if (*NewFileName != 0) {
//
// File was not found. We do not allow rename of the current directory if
// there are open files below the current directory
//
if (!IsListEmpty (&OFile->ChildHead) || Parent == OFile) {
return EFI_ACCESS_DENIED;
}
if (ReadOnly) {
return EFI_ACCESS_DENIED;
}
Status = FatRemoveDirEnt (OFile->Parent, DirEnt);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Create new dirent
//
Status = FatCreateDirEnt (Parent, NewFileName, DirEnt->Entry.Attributes, &TempDirEnt);
if (EFI_ERROR (Status)) {
return Status;
}
FatCloneDirEnt (TempDirEnt, DirEnt);
FatFreeDirEnt (DirEnt);
DirEnt = TempDirEnt;
DirEnt->OFile = OFile;
OFile->DirEnt = DirEnt;
OFile->Parent = Parent;
RemoveEntryList (&OFile->ChildLink);
InsertHeadList (&Parent->ChildHead, &OFile->ChildLink);
//
// If this is a directory, synchronize its dot directory entry
//
if (OFile->ODir != NULL) {
//
// Syncronize its dot entry
//
FatResetODirCursor (OFile);
ASSERT (OFile->Parent != NULL);
for (DotOFile = OFile; DotOFile != OFile->Parent->Parent; DotOFile = DotOFile->Parent) {
Status = FatGetNextDirEnt (OFile, &DirEnt);
if (EFI_ERROR (Status) || DirEnt == NULL || !FatIsDotDirEnt (DirEnt)) {
return EFI_VOLUME_CORRUPTED;
}
FatCloneDirEnt (DirEnt, DotOFile->DirEnt);
Status = FatStoreDirEnt (OFile, DirEnt);
if (EFI_ERROR (Status)) {
return Status;
}
}
}
//
// If the file is renamed, we should append the ARCHIVE attribute
//
OFile->Archive = TRUE;
} else if (Parent != OFile) {
//
// filename is to a different filename that already exists
//
return EFI_ACCESS_DENIED;
}
//
// If the file size has changed, apply it
//
if (NewInfo->FileSize != OFile->FileSize) {
if (OFile->ODir != NULL || ReadOnly) {
//
// If this is a directory or the file is read only, we can't change the file size
//
return EFI_ACCESS_DENIED;
}
if (NewInfo->FileSize > OFile->FileSize) {
Status = FatExpandOFile (OFile, NewInfo->FileSize);
} else {
Status = FatTruncateOFile (OFile, (UINTN) NewInfo->FileSize);
}
if (EFI_ERROR (Status)) {
return Status;
}
FatUpdateDirEntClusterSizeInfo (OFile);
}
OFile->Dirty = TRUE;
return FatOFileFlush (OFile);
}
EFI_STATUS
FatSetOrGetInfo (
IN BOOLEAN IsSet,
IN EFI_FILE *FHand,
IN EFI_GUID *Type,
IN OUT UINTN *BufferSize,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Set or Get the some types info of the file into Buffer
Arguments:
IsSet - TRUE:The access is set, else is get
FHand - The handle of file
Type - The type of the info
BufferSize - Size of Buffer
Buffer - Buffer containing volume info
Returns:
EFI_SUCCESS - Get the info successfully
EFI_DEVICE_ERROR - Can not find the OFile for the file
--*/
{
FAT_IFILE *IFile;
FAT_OFILE *OFile;
FAT_VOLUME *Volume;
EFI_STATUS Status;
IFile = IFILE_FROM_FHAND (FHand);
OFile = IFile->OFile;
Volume = OFile->Volume;
Status = OFile->Error;
if (Status == EFI_NOT_FOUND) {
return EFI_DEVICE_ERROR;
}
FatAcquireLock ();
//
// Verify the file handle isn't in an error state
//
if (!EFI_ERROR (Status)) {
//
// Get the proper information based on the request
//
Status = EFI_UNSUPPORTED;
if (IsSet) {
if (Volume->ReadOnly) {
Status = EFI_WRITE_PROTECTED;
} else {
if (CompareGuid (Type, &gEfiFileInfoGuid)) {
Status = FatSetFileInfo (Volume, IFile, OFile, *BufferSize, Buffer);
}
if (CompareGuid (Type, &gEfiFileSystemInfoGuid)) {
Status = FatSetVolumeInfo (Volume, *BufferSize, Buffer);
}
if (CompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
Status = FatSetVolumeLabelInfo (Volume, *BufferSize, Buffer);
}
}
} else {
if (CompareGuid (Type, &gEfiFileInfoGuid)) {
Status = FatGetFileInfo (OFile, BufferSize, Buffer);
}
if (CompareGuid (Type, &gEfiFileSystemInfoGuid)) {
Status = FatGetVolumeInfo (Volume, BufferSize, Buffer);
}
if (CompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
Status = FatGetVolumeLabelInfo (Volume, BufferSize, Buffer);
}
}
}
Status = FatCleanupVolume (Volume, NULL, Status);
FatReleaseLock ();
return Status;
}
EFI_STATUS
EFIAPI
FatGetInfo (
IN EFI_FILE *FHand,
IN EFI_GUID *Type,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Get the some types info of the file into Buffer.
Arguments:
FHand - The handle of file.
Type - The type of the info.
BufferSize - Size of Buffer.
Buffer - Buffer containing volume info.
Returns:
EFI_SUCCESS - Get the info successfully.
EFI_DEVICE_ERROR - Can not find the OFile for the file.
--*/
{
return FatSetOrGetInfo (FALSE, FHand, Type, BufferSize, Buffer);
}
EFI_STATUS
EFIAPI
FatSetInfo (
IN EFI_FILE *FHand,
IN EFI_GUID *Type,
IN UINTN BufferSize,
IN VOID *Buffer
)
/*++
Routine Description:
Set the some types info of the file into Buffer.
Arguments:
FHand - The handle of file.
Type - The type of the info.
BufferSize - Size of Buffer
Buffer - Buffer containing volume info.
Returns:
EFI_SUCCESS - Set the info successfully.
EFI_DEVICE_ERROR - Can not find the OFile for the file.
--*/
{
return FatSetOrGetInfo (TRUE, FHand, Type, &BufferSize, Buffer);
}

View File

@ -0,0 +1,431 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Init.c
Abstract:
Initialization routines
--*/
#include "Fat.h"
EFI_STATUS
FatAllocateVolume (
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo
)
/*++
Routine Description:
Allocates volume structure, detects FAT file system, installs protocol,
and initialize cache.
Arguments:
Handle - The handle of parent device.
DiskIo - The DiskIo of parent device.
BlockIo - The BlockIo of parent devicel
Returns:
EFI_SUCCESS - Allocate a new volume successfully.
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
Others - Allocating a new volume failed.
--*/
{
EFI_STATUS Status;
FAT_VOLUME *Volume;
BOOLEAN LockedByMe;
LockedByMe = FALSE;
//
// Allocate a volume structure
//
Volume = AllocateZeroPool (sizeof (FAT_VOLUME));
if (Volume == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Acquire the lock.
// If caller has already acquired the lock, cannot lock it again.
//
if (!FatIsLocked ()) {
FatAcquireLock ();
LockedByMe = TRUE;
}
//
// Initialize the structure
//
Volume->Signature = FAT_VOLUME_SIGNATURE;
Volume->Handle = Handle;
Volume->DiskIo = DiskIo;
Volume->BlockIo = BlockIo;
Volume->MediaId = BlockIo->Media->MediaId;
Volume->ReadOnly = BlockIo->Media->ReadOnly;
Volume->VolumeInterface.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
Volume->VolumeInterface.OpenVolume = FatOpenVolume;
InitializeListHead (&Volume->CheckRef);
InitializeListHead (&Volume->DirCacheList);
//
// Initialize Root Directory entry
//
Volume->RootDirEnt.FileString = Volume->RootFileString;
Volume->RootDirEnt.Entry.Attributes = FAT_ATTRIBUTE_DIRECTORY;
//
// Check to see if there's a file system on the volume
//
Status = FatOpenDevice (Volume);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Initialize cache
//
Status = FatInitializeDiskCache (Volume);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Install our protocol interfaces on the device's handle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Volume->Handle,
&gEfiSimpleFileSystemProtocolGuid,
&Volume->VolumeInterface,
NULL
);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Volume installed
//
DEBUG ((EFI_D_INIT, "%HInstalled Fat filesystem on %x%N\n", Handle));
Volume->Valid = TRUE;
Done:
//
// Unlock if locked by myself.
//
if (LockedByMe) {
FatReleaseLock ();
}
if (EFI_ERROR (Status)) {
FatFreeVolume (Volume);
}
return Status;
}
EFI_STATUS
FatAbandonVolume (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Called by FatDriverBindingStop(), Abandon the volume.
Arguments:
Volume - The volume to be abandoned.
Returns:
EFI_SUCCESS - Abandoned the volume successfully.
Others - Can not uninstall the protocol interfaces.
--*/
{
EFI_STATUS Status;
BOOLEAN LockedByMe;
//
// Uninstall the protocol interface.
//
if (Volume->Handle != NULL) {
Status = gBS->UninstallMultipleProtocolInterfaces (
Volume->Handle,
&gEfiSimpleFileSystemProtocolGuid,
&Volume->VolumeInterface,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
}
LockedByMe = FALSE;
//
// Acquire the lock.
// If the caller has already acquired the lock (which
// means we are in the process of some Fat operation),
// we can not acquire again.
//
if (!FatIsLocked ()) {
LockedByMe = TRUE;
FatAcquireLock ();
}
//
// The volume is still being used. Hence, set error flag for all OFiles still in
// use. In two cases, we could get here. One is EFI_MEDIA_CHANGED, the other is
// EFI_NO_MEDIA.
//
if (Volume->Root != NULL) {
FatSetVolumeError (
Volume->Root,
Volume->BlockIo->Media->MediaPresent ? EFI_MEDIA_CHANGED : EFI_NO_MEDIA
);
}
Volume->Valid = FALSE;
//
// Release the lock.
// If locked by me, this means DriverBindingStop is NOT
// called within an on-going Fat operation, so we should
// take responsibility to cleanup and free the volume.
// Otherwise, the DriverBindingStop is called within an on-going
// Fat operation, we shouldn't check reference, so just let outer
// FatCleanupVolume do the task.
//
if (LockedByMe) {
FatCleanupVolume (Volume, NULL, EFI_SUCCESS);
FatReleaseLock ();
}
return EFI_SUCCESS;
}
EFI_STATUS
FatOpenDevice (
IN OUT FAT_VOLUME *Volume
)
/*++
Routine Description:
Detects FAT file system on Disk and set relevant fields of Volume
Arguments:
Volume - The volume structure.
Returns:
EFI_SUCCESS - The Fat File System is detected successfully
EFI_UNSUPPORTED - The volume is not FAT file system.
EFI_VOLUME_CORRUPTED - The volume is corrupted.
--*/
{
EFI_STATUS Status;
UINT32 BlockSize;
UINT32 DirtyMask;
EFI_DISK_IO_PROTOCOL *DiskIo;
FAT_BOOT_SECTOR FatBs;
FAT_VOLUME_TYPE FatType;
UINTN RootDirSectors;
UINTN FatLba;
UINTN RootLba;
UINTN FirstClusterLba;
UINTN Sectors;
UINTN SectorsPerFat;
UINT8 SectorsPerClusterAlignment;
UINT8 BlockAlignment;
//
// Read the FAT_BOOT_SECTOR BPB info
// This is the only part of FAT code that uses parent DiskIo,
// Others use FatDiskIo which utilizes a Cache.
//
DiskIo = Volume->DiskIo;
Status = DiskIo->ReadDisk (DiskIo, Volume->MediaId, 0, sizeof (FatBs), &FatBs);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INIT, "FatOpenDevice: read of part_lba failed %r\n", Status));
return Status;
}
FatType = FatUndefined;
//
// Use LargeSectors if Sectors is 0
//
Sectors = FatBs.FatBsb.Sectors;
if (Sectors == 0) {
Sectors = FatBs.FatBsb.LargeSectors;
}
SectorsPerFat = FatBs.FatBsb.SectorsPerFat;
if (SectorsPerFat == 0) {
SectorsPerFat = FatBs.FatBse.Fat32Bse.LargeSectorsPerFat;
FatType = FAT32;
}
//
// Is boot sector a fat sector?
// (Note that so far we only know if the sector is FAT32 or not, we don't
// know if the sector is Fat16 or Fat12 until later when we can compute
// the volume size)
//
if (FatBs.FatBsb.ReservedSectors == 0 || FatBs.FatBsb.NumFats == 0 || Sectors == 0) {
return EFI_UNSUPPORTED;
}
if ((FatBs.FatBsb.SectorSize & (FatBs.FatBsb.SectorSize - 1)) != 0) {
return EFI_UNSUPPORTED;
}
BlockAlignment = (UINT8) HighBitSet32 (FatBs.FatBsb.SectorSize);
if (BlockAlignment > MAX_BLOCK_ALIGNMENT || BlockAlignment < MIN_BLOCK_ALIGNMENT) {
return EFI_UNSUPPORTED;
}
if ((FatBs.FatBsb.SectorsPerCluster & (FatBs.FatBsb.SectorsPerCluster - 1)) != 0) {
return EFI_UNSUPPORTED;
}
SectorsPerClusterAlignment = (UINT8) HighBitSet32 (FatBs.FatBsb.SectorsPerCluster);
if (SectorsPerClusterAlignment > MAX_SECTORS_PER_CLUSTER_ALIGNMENT) {
return EFI_UNSUPPORTED;
}
if (FatBs.FatBsb.Media <= 0xf7 &&
FatBs.FatBsb.Media != 0xf0 &&
FatBs.FatBsb.Media != 0x00 &&
FatBs.FatBsb.Media != 0x01
) {
return EFI_UNSUPPORTED;
}
//
// Initialize fields the volume information for this FatType
//
if (FatType != FAT32) {
if (FatBs.FatBsb.RootEntries == 0) {
return EFI_UNSUPPORTED;
}
//
// Unpack fat12, fat16 info
//
Volume->RootEntries = FatBs.FatBsb.RootEntries;
} else {
//
// If this is fat32, refuse to mount mirror-disabled volumes
//
if ((SectorsPerFat == 0 || FatBs.FatBse.Fat32Bse.FsVersion != 0) || (FatBs.FatBse.Fat32Bse.ExtendedFlags & 0x80)) {
return EFI_UNSUPPORTED;
}
//
// Unpack fat32 info
//
Volume->RootCluster = FatBs.FatBse.Fat32Bse.RootDirFirstCluster;
}
Volume->NumFats = FatBs.FatBsb.NumFats;
//
// Compute some fat locations
//
BlockSize = FatBs.FatBsb.SectorSize;
RootDirSectors = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (BlockSize - 1)) / BlockSize;
FatLba = FatBs.FatBsb.ReservedSectors;
RootLba = FatBs.FatBsb.NumFats * SectorsPerFat + FatLba;
FirstClusterLba = RootLba + RootDirSectors;
Volume->FatPos = FatLba * BlockSize;
Volume->FatSize = SectorsPerFat * BlockSize;
Volume->VolumeSize = LShiftU64 (Sectors, BlockAlignment);
Volume->RootPos = LShiftU64 (RootLba, BlockAlignment);
Volume->FirstClusterPos = LShiftU64 (FirstClusterLba, BlockAlignment);
Volume->MaxCluster = (Sectors - FirstClusterLba) >> SectorsPerClusterAlignment;
Volume->ClusterAlignment = (UINT8)(BlockAlignment + SectorsPerClusterAlignment);
Volume->ClusterSize = (UINTN)1 << (Volume->ClusterAlignment);
//
// If this is not a fat32, determine if it's a fat16 or fat12
//
if (FatType != FAT32) {
if (Volume->MaxCluster >= FAT_MAX_FAT16_CLUSTER) {
return EFI_VOLUME_CORRUPTED;
}
FatType = Volume->MaxCluster < FAT_MAX_FAT12_CLUSTER ? FAT12 : FAT16;
//
// fat12 & fat16 fat-entries are 2 bytes
//
Volume->FatEntrySize = sizeof (UINT16);
DirtyMask = FAT16_DIRTY_MASK;
} else {
if (Volume->MaxCluster < FAT_MAX_FAT16_CLUSTER) {
return EFI_VOLUME_CORRUPTED;
}
//
// fat32 fat-entries are 4 bytes
//
Volume->FatEntrySize = sizeof (UINT32);
DirtyMask = FAT32_DIRTY_MASK;
}
//
// Get the DirtyValue and NotDirtyValue
// We should keep the initial value as the NotDirtyValue
// in case the volume is dirty already
//
if (FatType != FAT12) {
Status = FatAccessVolumeDirty (Volume, READ_DISK, &Volume->NotDirtyValue);
if (EFI_ERROR (Status)) {
return Status;
}
Volume->DirtyValue = Volume->NotDirtyValue & DirtyMask;
}
//
// If present, read the fat hint info
//
if (FatType == FAT32) {
Volume->FreeInfoPos = FatBs.FatBse.Fat32Bse.FsInfoSector * BlockSize;
if (FatBs.FatBse.Fat32Bse.FsInfoSector != 0) {
FatDiskIo (Volume, READ_DISK, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector);
if (Volume->FatInfoSector.Signature == FAT_INFO_SIGNATURE &&
Volume->FatInfoSector.InfoBeginSignature == FAT_INFO_BEGIN_SIGNATURE &&
Volume->FatInfoSector.InfoEndSignature == FAT_INFO_END_SIGNATURE &&
Volume->FatInfoSector.FreeInfo.ClusterCount <= Volume->MaxCluster
) {
Volume->FreeInfoValid = TRUE;
}
}
}
//
// Just make up a FreeInfo.NextCluster for use by allocate cluster
//
if (FAT_MIN_CLUSTER > Volume->FatInfoSector.FreeInfo.NextCluster ||
Volume->FatInfoSector.FreeInfo.NextCluster > Volume->MaxCluster + 1
) {
Volume->FatInfoSector.FreeInfo.NextCluster = FAT_MIN_CLUSTER;
}
//
// We are now defining FAT Type
//
Volume->FatType = FatType;
ASSERT (FatType != FatUndefined);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,409 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Misc.c
Abstract:
Miscellaneous functions
Revision History
--*/
#include "Fat.h"
EFI_STATUS
FatAccessVolumeDirty (
IN FAT_VOLUME *Volume,
IN IO_MODE IoMode,
IN VOID *DirtyValue
)
/*++
Routine Description:
Set the volume as dirty or not
Arguments:
Volume - FAT file system volume.
IoMode - The access mode.
DirtyValue - Set the volume as dirty or not.
Returns:
EFI_SUCCESS - Set the new FAT entry value sucessfully.
other - An error occurred when operation the FAT entries.
--*/
{
UINTN WriteCount;
WriteCount = Volume->FatEntrySize;
return FatDiskIo (Volume, IoMode, Volume->FatPos + WriteCount, WriteCount, DirtyValue);
}
EFI_STATUS
FatDiskIo (
IN FAT_VOLUME *Volume,
IN IO_MODE IoMode,
IN UINT64 Offset,
IN UINTN BufferSize,
IN OUT VOID *Buffer
)
/*++
Routine Description:
General disk access function
Arguments:
Volume - FAT file system volume.
IoMode - The access mode (disk read/write or cache access).
Offset - The starting byte offset to read from.
BufferSize - Size of Buffer.
Buffer - Buffer containing read data.
Returns:
EFI_SUCCESS - The operation is performed successfully.
EFI_VOLUME_CORRUPTED - The accesss is
Others - The status of read/write the disk
--*/
{
EFI_STATUS Status;
EFI_DISK_IO_PROTOCOL *DiskIo;
EFI_DISK_READ IoFunction;
//
// Verify the IO is in devices range
//
Status = EFI_VOLUME_CORRUPTED;
if (Offset + BufferSize <= Volume->VolumeSize) {
if (CACHE_ENABLED (IoMode)) {
//
// Access cache
//
Status = FatAccessCache (Volume, CACHE_TYPE (IoMode), RAW_ACCESS (IoMode), Offset, BufferSize, Buffer);
} else {
//
// Access disk directly
//
DiskIo = Volume->DiskIo;
IoFunction = (IoMode == READ_DISK) ? DiskIo->ReadDisk : DiskIo->WriteDisk;
Status = IoFunction (DiskIo, Volume->MediaId, Offset, BufferSize, Buffer);
}
}
if (EFI_ERROR (Status)) {
Volume->DiskError = TRUE;
DEBUG ((EFI_D_INFO, "FatDiskIo: error %r\n", Status));
}
return Status;
}
VOID
FatAcquireLock (
VOID
)
/*++
Routine Description:
Lock the volume.
Arguments:
None.
Returns:
None.
--*/
{
EfiAcquireLock (&FatFsLock);
}
BOOLEAN
FatIsLocked (
VOID
)
/*++
Routine Description:
Get the locking status of the volume.
Arguments:
None.
Returns:
TRUE - The volume is locked.
FALSE - The volume is not locked.
--*/
{
return (BOOLEAN) (FatFsLock.Lock);
}
VOID
FatReleaseLock (
VOID
)
/*++
Routine Description:
Unlock the volume.
Arguments:
Null.
Returns:
None.
--*/
{
EfiReleaseLock (&FatFsLock);
}
VOID
FatFreeDirEnt (
IN FAT_DIRENT *DirEnt
)
/*++
Routine Description:
Free directory entry.
Arguments:
DirEnt - The directory entry to be freed.
Returns:
None.
--*/
{
if (DirEnt->FileString != NULL) {
FreePool (DirEnt->FileString);
}
FreePool (DirEnt);
}
VOID
FatFreeVolume (
IN FAT_VOLUME *Volume
)
/*++
Routine Description:
Free volume structure (including the contents of directory cache and disk cache).
Arguments:
Volume - The volume structure to be freed.
Returns:
None.
--*/
{
//
// Free disk cache
//
if (Volume->CacheBuffer != NULL) {
FreePool (Volume->CacheBuffer);
}
//
// Free directory cache
//
FatCleanupODirCache (Volume);
FreePool (Volume);
}
VOID
FatEfiTimeToFatTime (
IN EFI_TIME *ETime,
OUT FAT_DATE_TIME *FTime
)
/*++
Routine Description:
Translate EFI time to FAT time.
Arguments:
ETime - The time of EFI_TIME.
FTime - The time of FAT_DATE_TIME.
Returns:
None.
--*/
{
//
// ignores timezone info in source ETime
//
if (ETime->Year > 1980) {
FTime->Date.Year = (UINT16) (ETime->Year - 1980);
}
if (ETime->Year >= 1980 + FAT_MAX_YEAR_FROM_1980) {
FTime->Date.Year = FAT_MAX_YEAR_FROM_1980;
}
FTime->Date.Month = ETime->Month;
FTime->Date.Day = ETime->Day;
FTime->Time.Hour = ETime->Hour;
FTime->Time.Minute = ETime->Minute;
FTime->Time.DoubleSecond = (UINT16) (ETime->Second / 2);
}
VOID
FatFatTimeToEfiTime (
IN FAT_DATE_TIME *FTime,
OUT EFI_TIME *ETime
)
/*++
Routine Description:
Translate Fat time to EFI time.
Arguments:
FTime - The time of FAT_DATE_TIME.
ETime - The time of EFI_TIME.
Returns:
None.
--*/
{
ETime->Year = (UINT16) (FTime->Date.Year + 1980);
ETime->Month = (UINT8) FTime->Date.Month;
ETime->Day = (UINT8) FTime->Date.Day;
ETime->Hour = (UINT8) FTime->Time.Hour;
ETime->Minute = (UINT8) FTime->Time.Minute;
ETime->Second = (UINT8) (FTime->Time.DoubleSecond * 2);
ETime->Nanosecond = 0;
ETime->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
ETime->Daylight = 0;
}
VOID
FatGetCurrentFatTime (
OUT FAT_DATE_TIME *FatNow
)
/*++
Routine Description:
Get Current FAT time.
Arguments:
FatNow - Current FAT time.
Returns:
None.
--*/
{
EFI_TIME Now;
gRT->GetTime (&Now, NULL);
FatEfiTimeToFatTime (&Now, FatNow);
}
BOOLEAN
FatIsValidTime (
IN EFI_TIME *Time
)
/*++
Routine Description:
Check whether a time is valid.
Arguments:
Time - The time of EFI_TIME.
Returns:
TRUE - The time is valid.
FALSE - The time is not valid.
--*/
{
static UINT8 MonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
UINTN Day;
BOOLEAN ValidTime;
ValidTime = TRUE;
//
// Check the fields for range problems
// Fat can only support from 1980
//
if (Time->Year < 1980 ||
Time->Month < 1 ||
Time->Month > 12 ||
Time->Day < 1 ||
Time->Day > 31 ||
Time->Hour > 23 ||
Time->Minute > 59 ||
Time->Second > 59 ||
Time->Nanosecond > 999999999
) {
ValidTime = FALSE;
} else {
//
// Perform a more specific check of the day of the month
//
Day = MonthDays[Time->Month - 1];
if (Time->Month == 2 && IS_LEAP_YEAR (Time->Year)) {
Day += 1;
//
// 1 extra day this month
//
}
if (Time->Day > Day) {
ValidTime = FALSE;
}
}
return ValidTime;
}

View File

@ -0,0 +1,285 @@
/*++
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
open.c
Abstract:
Routines dealing with file open
Revision History
--*/
#include "Fat.h"
EFI_STATUS
FatAllocateIFile (
IN FAT_OFILE *OFile,
OUT FAT_IFILE **PtrIFile
)
/*++
Routine Description:
Create an Open instance for the existing OFile.
The IFile of the newly opened file is passed out.
Arguments:
OFile - The file that serves as a starting reference point.
PtrIFile - The newly generated IFile instance.
Returns:
EFI_OUT_OF_RESOURCES - Can not allocate the memory for the IFile
EFI_SUCCESS - Create the new IFile for the OFile successfully
--*/
{
FAT_IFILE *IFile;
ASSERT_VOLUME_LOCKED (OFile->Volume);
//
// Allocate a new open instance
//
IFile = AllocateZeroPool (sizeof (FAT_IFILE));
if (IFile == NULL) {
return EFI_OUT_OF_RESOURCES;
}
IFile->Signature = FAT_IFILE_SIGNATURE;
CopyMem (&(IFile->Handle), &FatFileInterface, sizeof (EFI_FILE));
IFile->OFile = OFile;
InsertTailList (&OFile->Opens, &IFile->Link);
*PtrIFile = IFile;
return EFI_SUCCESS;
}
EFI_STATUS
FatOFileOpen (
IN FAT_OFILE *OFile,
OUT FAT_IFILE **NewIFile,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT8 Attributes
)
/*++
Routine Description:
Open a file for a file name relative to an existing OFile.
The IFile of the newly opened file is passed out.
Arguments:
OFile - The file that serves as a starting reference point.
NewIFile - The newly generated IFile instance.
FileName - The file name relative to the OFile.
OpenMode - Open mode.
Attributes - Attributes to set if the file is created.
Returns:
EFI_SUCCESS - Open the file successfully.
EFI_INVALID_PARAMETER - The open mode is conflict with the attributes
or the file name is not valid.
EFI_NOT_FOUND - Conficts between dir intention and attribute.
EFI_WRITE_PROTECTED - Can't open for write if the volume is read only.
EFI_ACCESS_DENIED - If the file's attribute is read only, and the
open is for read-write fail it.
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
--*/
{
FAT_VOLUME *Volume;
EFI_STATUS Status;
CHAR16 NewFileName[EFI_PATH_STRING_LENGTH];
FAT_DIRENT *DirEnt;
UINT8 FileAttributes;
BOOLEAN WriteMode;
Volume = OFile->Volume;
ASSERT_VOLUME_LOCKED (Volume);
WriteMode = (BOOLEAN) (OpenMode & EFI_FILE_MODE_WRITE);
if (Volume->ReadOnly && WriteMode) {
return EFI_WRITE_PROTECTED;
}
//
// Verify the source file handle isn't in an error state
//
Status = OFile->Error;
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get new OFile for the file
//
Status = FatLocateOFile (&OFile, FileName, Attributes, NewFileName);
if (EFI_ERROR (Status)) {
return Status;
}
if (*NewFileName != 0) {
//
// If there's a remaining part of the name, then we had
// better be creating the file in the directory
//
if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) {
return EFI_NOT_FOUND;
}
Status = FatCreateDirEnt (OFile, NewFileName, Attributes, &DirEnt);
if (EFI_ERROR (Status)) {
return Status;
}
Status = FatOpenDirEnt (OFile, DirEnt);
if (EFI_ERROR (Status)) {
return Status;
}
OFile = DirEnt->OFile;
if (OFile->ODir != NULL) {
//
// If we just created a directory, we need to create "." and ".."
//
Status = FatCreateDotDirEnts (OFile);
if (EFI_ERROR (Status)) {
return Status;
}
}
}
//
// If the file's attribute is read only, and the open is for
// read-write, then the access is denied.
//
FileAttributes = OFile->DirEnt->Entry.Attributes;
if ((FileAttributes & EFI_FILE_READ_ONLY) != 0 && (FileAttributes & FAT_ATTRIBUTE_DIRECTORY) == 0 && WriteMode) {
return EFI_ACCESS_DENIED;
}
//
// Create an open instance of the OFile
//
Status = FatAllocateIFile (OFile, NewIFile);
if (EFI_ERROR (Status)) {
return Status;
}
(*NewIFile)->ReadOnly = (BOOLEAN)!WriteMode;
DEBUG ((EFI_D_INFO, "FSOpen: Open '%S' %r\n", FileName, Status));
return FatOFileFlush (OFile);
}
EFI_STATUS
EFIAPI
FatOpen (
IN EFI_FILE *FHand,
OUT EFI_FILE **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
/*++
Routine Description:
Implements Open() of Simple File System Protocol.
Arguments:
FHand - File handle of the file serves as a starting reference point.
NewHandle - Handle of the file that is newly opened.
FileName - File name relative to FHand.
OpenMode - Open mode.
Attributes - Attributes to set if the file is created.
Returns:
EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty.
The OpenMode is not supported.
The Attributes is not the valid attributes.
EFI_OUT_OF_RESOURCES - Can not allocate the memory for file string.
EFI_SUCCESS - Open the file successfully.
Others - The status of open file.
--*/
{
FAT_IFILE *IFile;
FAT_IFILE *NewIFile;
FAT_OFILE *OFile;
EFI_STATUS Status;
//
// Perform some parameter checking
//
if (FileName == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Check for a valid mode
//
switch (OpenMode) {
case EFI_FILE_MODE_READ:
case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:
break;
default:
return EFI_INVALID_PARAMETER;
}
//
// Check for valid attributes
//
if (Attributes & (~EFI_FILE_VALID_ATTR)) {
return EFI_INVALID_PARAMETER;
}
//
// Can't open for create and apply the read only attribute
//
if ((OpenMode & EFI_FILE_MODE_CREATE) && (Attributes & EFI_FILE_READ_ONLY)) {
return EFI_INVALID_PARAMETER;
}
IFile = IFILE_FROM_FHAND (FHand);
OFile = IFile->OFile;
//
// Lock
//
FatAcquireLock ();
//
// Open the file
//
Status = FatOFileOpen (OFile, &NewIFile, FileName, OpenMode, (UINT8) Attributes);
//
// If the file was opened, return the handle to the caller
//
if (!EFI_ERROR (Status)) {
*NewHandle = &NewIFile->Handle;
}
//
// Unlock
//
Status = FatCleanupVolume (OFile->Volume, NULL, Status);
FatReleaseLock ();
return Status;
}

View File

@ -0,0 +1,80 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
OpenVolume.c
Abstract:
OpenVolume() function of Simple File System Protocol
Revision History
--*/
#include "Fat.h"
EFI_STATUS
EFIAPI
FatOpenVolume (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
OUT EFI_FILE **File
)
/*++
Routine Description:
Implements Simple File System Protocol interface function OpenVolume().
Arguments:
This - Calling context.
File - the Root Directory of the volume.
Returns:
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
EFI_VOLUME_CORRUPTED - The FAT type is error.
EFI_SUCCESS - Open the volume successfully.
--*/
{
EFI_STATUS Status;
FAT_VOLUME *Volume;
FAT_IFILE *IFile;
Volume = VOLUME_FROM_VOL_INTERFACE (This);
FatAcquireLock ();
//
// Open Root file
//
Status = FatOpenDirEnt (NULL, &Volume->RootDirEnt);
if (EFI_ERROR (Status)) {
goto Done;
}
//
// Open a new instance to the root
//
Status = FatAllocateIFile (Volume->Root, &IFile);
if (!EFI_ERROR (Status)) {
*File = &IFile->Handle;
}
Done:
Status = FatCleanupVolume (Volume, Volume->Root, Status);
FatReleaseLock ();
return Status;
}

View File

@ -0,0 +1,612 @@
/*++
Copyright (c) 2005, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ReadWrite.c
Abstract:
Functions that perform file read/write
Revision History
--*/
#include "Fat.h"
EFI_STATUS
EFIAPI
FatGetPosition (
IN EFI_FILE *FHand,
OUT UINT64 *Position
)
/*++
Routine Description:
Get the file's position of the file.
Arguments:
FHand - The handle of file.
Position - The file's position of the file.
Returns:
EFI_SUCCESS - Get the info successfully.
EFI_DEVICE_ERROR - Can not find the OFile for the file.
EFI_UNSUPPORTED - The open file is not a file.
--*/
{
FAT_IFILE *IFile;
FAT_OFILE *OFile;
IFile = IFILE_FROM_FHAND (FHand);
OFile = IFile->OFile;
if (OFile->Error == EFI_NOT_FOUND) {
return EFI_DEVICE_ERROR;
}
if (OFile->ODir != NULL) {
return EFI_UNSUPPORTED;
}
*Position = IFile->Position;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
FatSetPosition (
IN EFI_FILE *FHand,
IN UINT64 Position
)
/*++
Routine Description:
Set the file's position of the file.
Arguments:
FHand - The handle of file.
Position - The file's position of the file.
Returns:
EFI_SUCCESS - Set the info successfully.
EFI_DEVICE_ERROR - Can not find the OFile for the file.
EFI_UNSUPPORTED - Set a directory with a not-zero position.
--*/
{
FAT_IFILE *IFile;
FAT_OFILE *OFile;
IFile = IFILE_FROM_FHAND (FHand);
OFile = IFile->OFile;
if (OFile->Error == EFI_NOT_FOUND) {
return EFI_DEVICE_ERROR;
}
//
// If this is a directory, we can only set back to position 0
//
if (OFile->ODir != NULL) {
if (Position != 0) {
//
// Reset current directory cursor;
//
return EFI_UNSUPPORTED;
}
FatResetODirCursor (OFile);
}
//
// Set the position
//
if (Position == -1) {
Position = OFile->FileSize;
}
//
// Set the position
//
IFile->Position = Position;
return EFI_SUCCESS;
}
EFI_STATUS
FatIFileReadDir (
IN FAT_IFILE *IFile,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Get the file info from the open file of the IFile into Buffer.
Arguments:
IFile - The instance of the open file.
BufferSize - Size of Buffer.
Buffer - Buffer containing read data.
Returns:
EFI_SUCCESS - Get the file info successfully.
other - An error occurred when operation the disk.
--*/
{
EFI_STATUS Status;
FAT_OFILE *OFile;
FAT_ODIR *ODir;
FAT_DIRENT *DirEnt;
UINT32 CurrentPos;
OFile = IFile->OFile;
ODir = OFile->ODir;
CurrentPos = ((UINT32) IFile->Position) / sizeof (FAT_DIRECTORY_ENTRY);
//
// We need to relocate the directory
//
if (CurrentPos < ODir->CurrentPos) {
//
// The directory cursor has been modified by another IFile, we reset the cursor
//
FatResetODirCursor (OFile);
}
//
// We seek the next directory entry's position
//
do {
Status = FatGetNextDirEnt (OFile, &DirEnt);
if (EFI_ERROR (Status) || DirEnt == NULL) {
//
// Something error occurred or reach the end of directory,
// return 0 buffersize
//
*BufferSize = 0;
goto Done;
}
} while (ODir->CurrentPos <= CurrentPos);
Status = FatGetDirEntInfo (OFile->Volume, DirEnt, BufferSize, Buffer);
Done:
//
// Update IFile's Position
//
if (!EFI_ERROR (Status)) {
//
// Update IFile->Position, if everything is all right
//
CurrentPos = ODir->CurrentPos;
IFile->Position = (UINT64) (CurrentPos * sizeof (FAT_DIRECTORY_ENTRY));
}
return Status;
}
EFI_STATUS
FatIFileAccess (
IN EFI_FILE *FHand,
IN IO_MODE IoMode,
IN OUT UINTN *BufferSize,
IN OUT VOID *Buffer
)
/*++
Routine Description:
Get the file info from the open file of the IFile into Buffer.
Arguments:
FHand - The file handle to access.
IoMode - Indicate whether the access mode is reading or writing.
BufferSize - Size of Buffer.
Buffer - Buffer containing read data.
Returns:
EFI_SUCCESS - Get the file info successfully.
EFI_DEVICE_ERROR - Can not find the OFile for the file.
EFI_VOLUME_CORRUPTED - The file type of open file is error.
EFI_WRITE_PROTECTED - The disk is write protect.
EFI_ACCESS_DENIED - The file is read-only.
other - An error occurred when operating on the disk.
--*/
{
EFI_STATUS Status;
FAT_IFILE *IFile;
FAT_OFILE *OFile;
FAT_VOLUME *Volume;
UINT64 EndPosition;
IFile = IFILE_FROM_FHAND (FHand);
OFile = IFile->OFile;
Volume = OFile->Volume;
if (OFile->Error == EFI_NOT_FOUND) {
return EFI_DEVICE_ERROR;
}
if (IoMode == READ_DATA) {
//
// If position is at EOF, then return device error
//
if (IFile->Position > OFile->FileSize) {
return EFI_DEVICE_ERROR;
}
} else {
//
// Check if the we can write data
//
if (Volume->ReadOnly) {
return EFI_WRITE_PROTECTED;
}
if (IFile->ReadOnly) {
return EFI_ACCESS_DENIED;
}
}
FatAcquireLock ();
Status = OFile->Error;
if (!EFI_ERROR (Status)) {
if (OFile->ODir != NULL) {
//
// Access a directory
//
Status = EFI_UNSUPPORTED;
if (IoMode == READ_DATA) {
//
// Read a directory is supported
//
Status = FatIFileReadDir (IFile, BufferSize, Buffer);
}
OFile = NULL;
} else {
//
// Access a file
//
EndPosition = IFile->Position + *BufferSize;
if (EndPosition > OFile->FileSize) {
//
// The position goes beyond the end of file
//
if (IoMode == READ_DATA) {
//
// Adjust the actual size read
//
*BufferSize -= (UINTN) EndPosition - OFile->FileSize;
} else {
//
// We expand the file size of OFile
//
Status = FatGrowEof (OFile, EndPosition);
if (EFI_ERROR (Status)) {
//
// Must update the file's info into the file's Directory Entry
// and then flush the dirty cache info into disk.
//
*BufferSize = 0;
FatOFileFlush (OFile);
OFile = NULL;
goto Done;
}
FatUpdateDirEntClusterSizeInfo (OFile);
}
}
Status = FatAccessOFile (OFile, IoMode, (UINTN) IFile->Position, BufferSize, Buffer);
IFile->Position += *BufferSize;
}
}
Done:
if (EFI_ERROR (Status)) {
Status = FatCleanupVolume (Volume, OFile, Status);
}
//
// On EFI_SUCCESS case, not calling FatCleanupVolume():
// 1) The Cache flush operation is avoided to enhance
// performance. Caller is responsible to call Flush() when necessary.
// 2) The volume dirty bit is probably set already, and is expected to be
// cleaned in subsequent Flush() or other operations.
// 3) Write operation doesn't affect OFile/IFile structure, so
// Reference checking is not necessary.
//
FatReleaseLock ();
return Status;
}
EFI_STATUS
EFIAPI
FatRead (
IN EFI_FILE *FHand,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Get the file info.
Arguments:
FHand - The handle of the file.
BufferSize - Size of Buffer.
Buffer - Buffer containing read data.
Returns:
EFI_SUCCESS - Get the file info successfully.
EFI_DEVICE_ERROR - Can not find the OFile for the file.
EFI_VOLUME_CORRUPTED - The file type of open file is error.
other - An error occurred when operation the disk.
--*/
{
return FatIFileAccess (FHand, READ_DATA, BufferSize, Buffer);
}
EFI_STATUS
EFIAPI
FatWrite (
IN EFI_FILE *FHand,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
)
/*++
Routine Description:
Write the content of buffer into files.
Arguments:
FHand - The handle of the file.
BufferSize - Size of Buffer.
Buffer - Buffer containing write data.
Returns:
EFI_SUCCESS - Set the file info successfully.
EFI_WRITE_PROTECTED - The disk is write protect.
EFI_ACCESS_DENIED - The file is read-only.
EFI_DEVICE_ERROR - The OFile is not valid.
EFI_UNSUPPORTED - The open file is not a file.
- The writing file size is larger than 4GB.
other - An error occurred when operation the disk.
--*/
{
return FatIFileAccess (FHand, WRITE_DATA, BufferSize, Buffer);
}
EFI_STATUS
FatAccessOFile (
IN FAT_OFILE *OFile,
IN IO_MODE IoMode,
IN UINTN Position,
IN OUT UINTN *DataBufferSize,
IN OUT UINT8 *UserBuffer
)
/*++
Routine Description:
This function reads data from a file or writes data to a file.
It uses OFile->PosRem to determine how much data can be accessed in one time.
Arguments:
OFile - The open file.
IoMode - Indicate whether the access mode is reading or writing.
Position - The position where data will be accessed.
DataBufferSize - Size of Buffer.
UserBuffer - Buffer containing data.
Returns:
EFI_SUCCESS - Access the data successfully.
other - An error occurred when operating on the disk.
--*/
{
FAT_VOLUME *Volume;
UINTN Len;
EFI_STATUS Status;
UINTN BufferSize;
BufferSize = *DataBufferSize;
Volume = OFile->Volume;
ASSERT_VOLUME_LOCKED (Volume);
Status = EFI_SUCCESS;
while (BufferSize > 0) {
//
// Seek the OFile to the file position
//
Status = FatOFilePosition (OFile, Position, BufferSize);
if (EFI_ERROR (Status)) {
break;
}
//
// Clip length to block run
//
Len = BufferSize > OFile->PosRem ? OFile->PosRem : BufferSize;
//
// Write the data
//
Status = FatDiskIo (Volume, IoMode, OFile->PosDisk, Len, UserBuffer);
if (EFI_ERROR (Status)) {
break;
}
//
// Data was successfully accessed
//
Position += Len;
UserBuffer += Len;
BufferSize -= Len;
if (IoMode == WRITE_DATA) {
OFile->Dirty = TRUE;
OFile->Archive = TRUE;
}
//
// Make sure no outbound occurred
//
ASSERT (Position <= OFile->FileSize);
}
//
// Update the number of bytes accessed
//
*DataBufferSize -= BufferSize;
return Status;
}
EFI_STATUS
FatExpandOFile (
IN FAT_OFILE *OFile,
IN UINT64 ExpandedSize
)
/*++
Routine Description:
Expand OFile by appending zero bytes at the end of OFile.
Arguments:
OFile - The open file.
ExpandedSize - The number of zero bytes appended at the end of the file.
Returns:
EFI_SUCCESS - The file is expanded successfully.
other - An error occurred when expanding file.
--*/
{
EFI_STATUS Status;
UINTN WritePos;
WritePos = OFile->FileSize;
Status = FatGrowEof (OFile, ExpandedSize);
if (!EFI_ERROR (Status)) {
Status = FatWriteZeroPool (OFile, WritePos);
}
return Status;
}
EFI_STATUS
FatWriteZeroPool (
IN FAT_OFILE *OFile,
IN UINTN WritePos
)
/*++
Routine Description:
Write zero pool from the WritePos to the end of OFile.
Arguments:
OFile - The open file to write zero pool.
WritePos - The number of zero bytes written.
Returns:
EFI_SUCCESS - Write the zero pool successfully.
EFI_OUT_OF_RESOURCES - Not enough memory to perform the operation.
other - An error occurred when writing disk.
--*/
{
EFI_STATUS Status;
VOID *ZeroBuffer;
UINTN AppendedSize;
UINTN BufferSize;
UINTN WriteSize;
AppendedSize = OFile->FileSize - WritePos;
BufferSize = AppendedSize;
if (AppendedSize > FAT_MAX_ALLOCATE_SIZE) {
//
// If the appended size is larger, maybe we can not allocate the whole
// memory once. So if the growed size is larger than 10M, we just
// allocate 10M memory (one healthy system should have 10M available
// memory), and then write the zerobuffer to the file several times.
//
BufferSize = FAT_MAX_ALLOCATE_SIZE;
}
ZeroBuffer = AllocateZeroPool (BufferSize);
if (ZeroBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
do {
WriteSize = AppendedSize > BufferSize ? BufferSize : (UINTN) AppendedSize;
AppendedSize -= WriteSize;
Status = FatAccessOFile (OFile, WRITE_DATA, WritePos, &WriteSize, ZeroBuffer);
if (EFI_ERROR (Status)) {
break;
}
WritePos += WriteSize;
} while (AppendedSize > 0);
FreePool (ZeroBuffer);
return Status;
}
EFI_STATUS
FatTruncateOFile (
IN FAT_OFILE *OFile,
IN UINTN TruncatedSize
)
/*++
Routine Description:
Truncate the OFile to smaller file size.
Arguments:
OFile - The open file.
TruncatedSize - The new file size.
Returns:
EFI_SUCCESS - The file is truncated successfully.
other - An error occurred when truncating file.
--*/
{
OFile->FileSize = TruncatedSize;
return FatShrinkEof (OFile);
}

View File

@ -0,0 +1,324 @@
/** @file
Unicode Collation Library that hides the trival difference of Unicode Collation
and Unicode collation 2 Protocol.
Copyright (c) 2007, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Guid/GlobalVariable.h>
#include <Protocol/UnicodeCollation.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
STATIC EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollationInterface = NULL;
typedef
BOOLEAN
(* SEARCH_LANG_CODE) (
IN CONST CHAR8 *Languages,
IN CONST CHAR8 *MatchLangCode
);
struct _UNICODE_INTERFACE {
CHAR16 *VariableName;
CHAR8 *DefaultLangCode;
SEARCH_LANG_CODE SearchLangCode;
EFI_GUID *UnicodeProtocolGuid;
};
typedef struct _UNICODE_INTERFACE UNICODE_INTERFACE;
STATIC
BOOLEAN
SearchIso639LangCode (
IN CONST CHAR8 *Languages,
IN CONST CHAR8 *MatchLangCode
)
{
CONST CHAR8 *LangCode;
for (LangCode = Languages; *LangCode != '\0'; LangCode += 3) {
if (CompareMem (LangCode, MatchLangCode, 3) == 0) {
return TRUE;
}
}
return FALSE;
}
STATIC
BOOLEAN
SearchRfc3066LangCode (
IN CONST CHAR8 *Languages,
IN CONST CHAR8 *MatchLangCode
)
{
CHAR8 *SubStr;
CHAR8 Terminal;
SubStr = AsciiStrStr (Languages, MatchLangCode);
if (SubStr == NULL) {
return FALSE;
}
if (SubStr != Languages && *(SubStr - 1) != ';') {
return FALSE;
}
Terminal = *(SubStr + AsciiStrLen (MatchLangCode));
if (Terminal != '\0' && Terminal != ';') {
return FALSE;
}
return TRUE;
}
GLOBAL_REMOVE_IF_UNREFERENCED UNICODE_INTERFACE mIso639Lang = {
L"Lang",
(CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang),
SearchIso639LangCode,
&gEfiUnicodeCollationProtocolGuid,
};
GLOBAL_REMOVE_IF_UNREFERENCED UNICODE_INTERFACE mRfc3066Lang = {
L"PlatformLang",
(CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
SearchRfc3066LangCode,
&gEfiUnicodeCollation2ProtocolGuid,
};
STATIC
EFI_STATUS
InitializeUnicodeCollationSupportWithConfig (
IN EFI_HANDLE AgentHandle,
IN UNICODE_INTERFACE *UnicodeInterface
)
{
EFI_STATUS Status;
CHAR8 Buffer[100];
UINTN BufferSize;
UINTN Index;
CHAR8 *LangCode;
UINTN NoHandles;
EFI_HANDLE *Handles;
EFI_UNICODE_COLLATION_PROTOCOL *Uci;
LangCode = Buffer;
BufferSize = sizeof (Buffer);
Status = gRT->GetVariable (
UnicodeInterface->VariableName,
&gEfiGlobalVariableGuid,
NULL,
&BufferSize,
Buffer
);
if (EFI_ERROR (Status)) {
LangCode = UnicodeInterface->DefaultLangCode;
}
Status = gBS->LocateHandleBuffer (
ByProtocol,
UnicodeInterface->UnicodeProtocolGuid,
NULL,
&NoHandles,
&Handles
);
if (EFI_ERROR (Status)) {
return Status;
}
for (Index = 0; Index < NoHandles; Index++) {
//
// Open Unicode Collation Protocol
//
Status = gBS->OpenProtocol (
Handles[Index],
UnicodeInterface->UnicodeProtocolGuid,
(VOID **) &Uci,
AgentHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
continue;
}
if (UnicodeInterface->SearchLangCode (Uci->SupportedLanguages, LangCode)) {
mUnicodeCollationInterface = Uci;
break;
}
}
FreePool (Handles);
return (mUnicodeCollationInterface != NULL)? EFI_SUCCESS : EFI_NOT_FOUND;
}
/**
Initialize Unicode Collation support.
@param AgentHandle The handle used to open Unicode Collation (2) protocol.
@retval EFI_SUCCESS The Unicode Collation (2) protocol has been successfully located.
@retval Others The Unicode Collation (2) protocol has not been located.
**/
EFI_STATUS
InitializeUnicodeCollationSupport (
IN EFI_HANDLE AgentHandle
)
{
EFI_STATUS Status;
Status = EFI_UNSUPPORTED;
if (FeaturePcdGet (PcdUnicodeCollation2Support)) {
Status = InitializeUnicodeCollationSupportWithConfig (AgentHandle, &mRfc3066Lang);
}
if (FeaturePcdGet (PcdUnicodeCollationSupport) && EFI_ERROR (Status)) {
Status = InitializeUnicodeCollationSupportWithConfig (AgentHandle, &mIso639Lang);
}
return Status;
}
/**
Performs a case-insensitive comparison of two Null-terminated Unicode strings.
@param S1 A pointer to a Null-terminated Unicode string.
@param S2 A pointer to a Null-terminated Unicode string.
@retval 0 S1 is equivalent to S2.
@retval >0 S1 is lexically greater than S2.
@retval <0 S1 is lexically less than S2.
**/
INTN
FatStriCmp (
IN CHAR16 *S1,
IN CHAR16 *S2
)
{
ASSERT (StrSize (S1) != 0);
ASSERT (StrSize (S2) != 0);
ASSERT (mUnicodeCollationInterface != NULL);
return mUnicodeCollationInterface->StriColl (
mUnicodeCollationInterface,
S1,
S2
);
}
/**
Uppercase a string.
@param Str The string which will be upper-cased.
@return None.
**/
VOID
FatStrUpr (
IN OUT CHAR16 *String
)
{
ASSERT (StrSize (String) != 0);
ASSERT (mUnicodeCollationInterface != NULL);
mUnicodeCollationInterface->StrUpr (mUnicodeCollationInterface, String);
}
/**
Lowercase a string
@param Str The string which will be lower-cased.
@return None
**/
VOID
FatStrLwr (
IN OUT CHAR16 *String
)
{
ASSERT (StrSize (String) != 0);
ASSERT (mUnicodeCollationInterface != NULL);
mUnicodeCollationInterface->StrLwr (mUnicodeCollationInterface, String);
}
/**
Convert FAT string to unicode string.
@param FatSize The size of FAT string.
@param Fat The FAT string.
@param String The unicode string.
@return None.
**/
VOID
FatFatToStr (
IN UINTN FatSize,
IN CHAR8 *Fat,
OUT CHAR16 *String
)
{
ASSERT (Fat != NULL);
ASSERT (String != NULL);
ASSERT (((UINTN) String & 0x01) != 0);
ASSERT (mUnicodeCollationInterface != NULL);
mUnicodeCollationInterface->FatToStr (mUnicodeCollationInterface, FatSize, Fat, String);
}
/**
Convert unicode string to Fat string.
@param String The unicode string.
@param FatSize The size of the FAT string.
@param Fat The FAT string.
@retval TRUE Convert successfully.
@retval FALSE Convert error.
**/
BOOLEAN
FatStrToFat (
IN CHAR16 *String,
IN UINTN FatSize,
OUT CHAR8 *Fat
)
{
ASSERT (Fat != NULL);
ASSERT (StrSize (String) != 0);
ASSERT (mUnicodeCollationInterface != NULL);
return mUnicodeCollationInterface->StrToFat (
mUnicodeCollationInterface,
String,
FatSize,
Fat
);
}

29
FatPkg/FatPkg.dec Normal file
View File

@ -0,0 +1,29 @@
#/** @file
#
# FAT Package
#
# FAT 32 Driver
# Copyright (c) 2007, Intel Corporation.
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#**/
[Defines]
DEC_VERSION = 0x00010005
PACKAGE_NAME = FatPkg
PACKAGE_GUID = 8EA68A2C-99CB-4332-85C6-DD5864EAA674
[PcdsFeatureFlag.common]
gEfiFatPkgTokenSpaceGuid.PcdUnicodeCollationSupport|TRUE|BOOLEAN|0x00010001
gEfiFatPkgTokenSpaceGuid.PcdUnicodeCollation2Support|TRUE|BOOLEAN|0x00010002
[Guids.common]
gEfiFatPkgTokenSpaceGuid = {0xc8e92dba, 0x1d92, 0x411f, {0xae, 0xa, 0x1d, 0xbe, 0xd8, 0xf1, 0x32, 0x99}};

49
FatPkg/FatPkg.dsc Normal file
View File

@ -0,0 +1,49 @@
#/** @file
#
# Build Binary Enhanced Fat Driver Modules
#
# This Platform file is used to generate the Binary Fat Drivers
# for EDK II Prime release.
# Copyright (c) 2007, Intel Corporation
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#**/
[Defines]
PLATFORM_NAME = Fat
PLATFORM_GUID = 25b55dbc-9d0b-4a32-80da-46e1273d622c
PLATFORM_VERSION = 0.1
DSC_SPECIFICATION = 0x00010005
SUPPORTED_ARCHITECTURES = IA32|X64|IPF|EBC
OUTPUT_DIRECTORY = Build/Fat
BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
[LibraryClasses.common]
#
# Entry Point Libraries
#
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
#
# Common Libraries
#
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
[Components.common]
FatPkg\EnhancedFatDxe\Fat.inf

11
FatPkg/License.txt Normal file
View File

@ -0,0 +1,11 @@
Copyright (c) 2006, Intel Corporation
All rights reserved.
This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

7
FatPkg/ReadMe.txt Normal file
View File

@ -0,0 +1,7 @@
EDK II Prime FAT Package
Build Validation:
MYTOOLS(VS2005) IA32 X64 IPF EBC
ICC IA32 X64 IPF
CYGWINGCC IA32 X64