mirror of https://github.com/acidanthera/audk.git
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:
parent
f0dc69e61b
commit
b9ec93308b
|
@ -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)
|
||||
);
|
||||
}
|
|
@ -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
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
|
@ -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}};
|
||||
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
EDK II Prime FAT Package
|
||||
|
||||
Build Validation:
|
||||
MYTOOLS(VS2005) IA32 X64 IPF EBC
|
||||
ICC IA32 X64 IPF
|
||||
CYGWINGCC IA32 X64
|
||||
|
Loading…
Reference in New Issue