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:
committed by
Jordan Justen
parent
f0dc69e61b
commit
b9ec93308b
355
FatPkg/EnhancedFatDxe/ComponentName.c
Normal file
355
FatPkg/EnhancedFatDxe/ComponentName.c
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
ComponentName.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// EFI Component Name Functions
|
||||||
|
//
|
||||||
|
/**
|
||||||
|
Retrieves a Unicode string that is the user readable name of the driver.
|
||||||
|
|
||||||
|
This function retrieves the user readable name of a driver in the form of a
|
||||||
|
Unicode string. If the driver specified by This has a user readable name in
|
||||||
|
the language specified by Language, then a pointer to the driver name is
|
||||||
|
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||||
|
by This does not support the language specified by Language,
|
||||||
|
then EFI_UNSUPPORTED is returned.
|
||||||
|
|
||||||
|
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||||
|
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||||
|
|
||||||
|
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||||
|
array indicating the language. This is the
|
||||||
|
language of the driver name that the caller is
|
||||||
|
requesting, and it must match one of the
|
||||||
|
languages specified in SupportedLanguages. The
|
||||||
|
number of languages supported by a driver is up
|
||||||
|
to the driver writer. Language is specified
|
||||||
|
in RFC 3066 or ISO 639-2 language code format.
|
||||||
|
|
||||||
|
@param DriverName[out] A pointer to the Unicode string to return.
|
||||||
|
This Unicode string is the name of the
|
||||||
|
driver specified by This in the language
|
||||||
|
specified by Language.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||||
|
This and the language specified by Language was
|
||||||
|
returned in DriverName.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||||
|
the language specified by Language.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatComponentNameGetDriverName (
|
||||||
|
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||||
|
IN CHAR8 *Language,
|
||||||
|
OUT CHAR16 **DriverName
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieves a Unicode string that is the user readable name of the controller
|
||||||
|
that is being managed by a driver.
|
||||||
|
|
||||||
|
This function retrieves the user readable name of the controller specified by
|
||||||
|
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||||
|
driver specified by This has a user readable name in the language specified by
|
||||||
|
Language, then a pointer to the controller name is returned in ControllerName,
|
||||||
|
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||||
|
managing the controller specified by ControllerHandle and ChildHandle,
|
||||||
|
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||||
|
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||||
|
|
||||||
|
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||||
|
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||||
|
|
||||||
|
@param ControllerHandle[in] The handle of a controller that the driver
|
||||||
|
specified by This is managing. This handle
|
||||||
|
specifies the controller whose name is to be
|
||||||
|
returned.
|
||||||
|
|
||||||
|
@param ChildHandle[in] The handle of the child controller to retrieve
|
||||||
|
the name of. This is an optional parameter that
|
||||||
|
may be NULL. It will be NULL for device
|
||||||
|
drivers. It will also be NULL for a bus drivers
|
||||||
|
that wish to retrieve the name of the bus
|
||||||
|
controller. It will not be NULL for a bus
|
||||||
|
driver that wishes to retrieve the name of a
|
||||||
|
child controller.
|
||||||
|
|
||||||
|
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||||
|
array indicating the language. This is the
|
||||||
|
language of the driver name that the caller is
|
||||||
|
requesting, and it must match one of the
|
||||||
|
languages specified in SupportedLanguages. The
|
||||||
|
number of languages supported by a driver is up
|
||||||
|
to the driver writer. Language is specified in
|
||||||
|
RFC 3066 or ISO 639-2 language code format.
|
||||||
|
|
||||||
|
@param ControllerName[out] A pointer to the Unicode string to return.
|
||||||
|
This Unicode string is the name of the
|
||||||
|
controller specified by ControllerHandle and
|
||||||
|
ChildHandle in the language specified by
|
||||||
|
Language from the point of view of the driver
|
||||||
|
specified by This.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The Unicode string for the user readable name in
|
||||||
|
the language specified by Language for the
|
||||||
|
driver specified by This was returned in
|
||||||
|
DriverName.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
|
||||||
|
EFI_HANDLE.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||||
|
managing the controller specified by
|
||||||
|
ControllerHandle and ChildHandle.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||||
|
the language specified by Language.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatComponentNameGetControllerName (
|
||||||
|
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE ControllerHandle,
|
||||||
|
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||||
|
IN CHAR8 *Language,
|
||||||
|
OUT CHAR16 **ControllerName
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// EFI Component Name Protocol
|
||||||
|
//
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gFatComponentName = {
|
||||||
|
FatComponentNameGetDriverName,
|
||||||
|
FatComponentNameGetControllerName,
|
||||||
|
"eng"
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// EFI Component Name 2 Protocol
|
||||||
|
//
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gFatComponentName2 = {
|
||||||
|
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) FatComponentNameGetDriverName,
|
||||||
|
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) FatComponentNameGetControllerName,
|
||||||
|
"en"
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mFatDriverNameTable[] = {
|
||||||
|
{
|
||||||
|
"eng;en",
|
||||||
|
L"FAT File System Driver"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mFatControllerNameTable[] = {
|
||||||
|
{
|
||||||
|
"eng;en",
|
||||||
|
L"FAT File System"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieves a Unicode string that is the user readable name of the driver.
|
||||||
|
|
||||||
|
This function retrieves the user readable name of a driver in the form of a
|
||||||
|
Unicode string. If the driver specified by This has a user readable name in
|
||||||
|
the language specified by Language, then a pointer to the driver name is
|
||||||
|
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||||
|
by This does not support the language specified by Language,
|
||||||
|
then EFI_UNSUPPORTED is returned.
|
||||||
|
|
||||||
|
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||||
|
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||||
|
|
||||||
|
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||||
|
array indicating the language. This is the
|
||||||
|
language of the driver name that the caller is
|
||||||
|
requesting, and it must match one of the
|
||||||
|
languages specified in SupportedLanguages. The
|
||||||
|
number of languages supported by a driver is up
|
||||||
|
to the driver writer. Language is specified
|
||||||
|
in RFC 3066 or ISO 639-2 language code format.
|
||||||
|
|
||||||
|
@param DriverName[out] A pointer to the Unicode string to return.
|
||||||
|
This Unicode string is the name of the
|
||||||
|
driver specified by This in the language
|
||||||
|
specified by Language.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||||
|
This and the language specified by Language was
|
||||||
|
returned in DriverName.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||||
|
the language specified by Language.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatComponentNameGetDriverName (
|
||||||
|
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||||
|
IN CHAR8 *Language,
|
||||||
|
OUT CHAR16 **DriverName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return LookupUnicodeString2 (
|
||||||
|
Language,
|
||||||
|
This->SupportedLanguages,
|
||||||
|
mFatDriverNameTable,
|
||||||
|
DriverName,
|
||||||
|
(BOOLEAN)(This == &gFatComponentName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieves a Unicode string that is the user readable name of the controller
|
||||||
|
that is being managed by a driver.
|
||||||
|
|
||||||
|
This function retrieves the user readable name of the controller specified by
|
||||||
|
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||||
|
driver specified by This has a user readable name in the language specified by
|
||||||
|
Language, then a pointer to the controller name is returned in ControllerName,
|
||||||
|
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||||
|
managing the controller specified by ControllerHandle and ChildHandle,
|
||||||
|
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||||
|
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||||
|
|
||||||
|
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||||
|
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||||
|
|
||||||
|
@param ControllerHandle[in] The handle of a controller that the driver
|
||||||
|
specified by This is managing. This handle
|
||||||
|
specifies the controller whose name is to be
|
||||||
|
returned.
|
||||||
|
|
||||||
|
@param ChildHandle[in] The handle of the child controller to retrieve
|
||||||
|
the name of. This is an optional parameter that
|
||||||
|
may be NULL. It will be NULL for device
|
||||||
|
drivers. It will also be NULL for a bus drivers
|
||||||
|
that wish to retrieve the name of the bus
|
||||||
|
controller. It will not be NULL for a bus
|
||||||
|
driver that wishes to retrieve the name of a
|
||||||
|
child controller.
|
||||||
|
|
||||||
|
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||||
|
array indicating the language. This is the
|
||||||
|
language of the driver name that the caller is
|
||||||
|
requesting, and it must match one of the
|
||||||
|
languages specified in SupportedLanguages. The
|
||||||
|
number of languages supported by a driver is up
|
||||||
|
to the driver writer. Language is specified in
|
||||||
|
RFC 3066 or ISO 639-2 language code format.
|
||||||
|
|
||||||
|
@param ControllerName[out] A pointer to the Unicode string to return.
|
||||||
|
This Unicode string is the name of the
|
||||||
|
controller specified by ControllerHandle and
|
||||||
|
ChildHandle in the language specified by
|
||||||
|
Language from the point of view of the driver
|
||||||
|
specified by This.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The Unicode string for the user readable name in
|
||||||
|
the language specified by Language for the
|
||||||
|
driver specified by This was returned in
|
||||||
|
DriverName.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
|
||||||
|
EFI_HANDLE.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||||
|
managing the controller specified by
|
||||||
|
ControllerHandle and ChildHandle.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||||
|
the language specified by Language.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatComponentNameGetControllerName (
|
||||||
|
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE ControllerHandle,
|
||||||
|
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||||
|
IN CHAR8 *Language,
|
||||||
|
OUT CHAR16 **ControllerName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is a device driver, so ChildHandle must be NULL.
|
||||||
|
//
|
||||||
|
if (ChildHandle != NULL) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure this driver is currently managing ControllHandle
|
||||||
|
//
|
||||||
|
Status = EfiTestManagedDevice (
|
||||||
|
ControllerHandle,
|
||||||
|
gFatDriverBinding.DriverBindingHandle,
|
||||||
|
&gEfiDiskIoProtocolGuid
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LookupUnicodeString2 (
|
||||||
|
Language,
|
||||||
|
This->SupportedLanguages,
|
||||||
|
mFatControllerNameTable,
|
||||||
|
ControllerName,
|
||||||
|
(BOOLEAN)(This == &gFatComponentName)
|
||||||
|
);
|
||||||
|
}
|
50
FatPkg/EnhancedFatDxe/Data.c
Normal file
50
FatPkg/EnhancedFatDxe/Data.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
Data.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Global data in the FAT Filesystem driver
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Globals
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// FatFsLock - Global lock for synchronizing all requests.
|
||||||
|
//
|
||||||
|
EFI_LOCK FatFsLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_CALLBACK);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Filesystem interface functions
|
||||||
|
//
|
||||||
|
EFI_FILE FatFileInterface = {
|
||||||
|
EFI_FILE_PROTOCOL_REVISION,
|
||||||
|
FatOpen,
|
||||||
|
FatClose,
|
||||||
|
FatDelete,
|
||||||
|
FatRead,
|
||||||
|
FatWrite,
|
||||||
|
FatGetPosition,
|
||||||
|
FatSetPosition,
|
||||||
|
FatGetInfo,
|
||||||
|
FatSetInfo,
|
||||||
|
FatFlush
|
||||||
|
};
|
80
FatPkg/EnhancedFatDxe/Debug.c
Normal file
80
FatPkg/EnhancedFatDxe/Debug.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
debug.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Debug functions for fat driver
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatDumpFatTable (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Dump all the FAT Entry of the FAT table in the volume
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - The volume whose FAT info will be dumped
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN EntryValue;
|
||||||
|
UINTN MaxIndex;
|
||||||
|
UINTN Index;
|
||||||
|
CHAR16 *Pointer;
|
||||||
|
|
||||||
|
MaxIndex = Volume->MaxCluster + 2;
|
||||||
|
|
||||||
|
Print (L"Dump of Fat Table, MaxCluster %x\n", MaxIndex);
|
||||||
|
for (Index = 0; Index < MaxIndex; Index++) {
|
||||||
|
EntryValue = FatGetFatEntry (Volume, Index);
|
||||||
|
if (EntryValue != FAT_CLUSTER_FREE) {
|
||||||
|
Pointer = NULL;
|
||||||
|
switch (EntryValue) {
|
||||||
|
case FAT_CLUSTER_RESERVED:
|
||||||
|
Pointer = L"RESREVED";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT_CLUSTER_BAD:
|
||||||
|
Pointer = L"BAD";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAT_END_OF_FAT_CHAIN (EntryValue)) {
|
||||||
|
Pointer = L"LAST";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Pointer != NULL) {
|
||||||
|
Print (L"Entry %x = %s\n", Index, Pointer);
|
||||||
|
} else {
|
||||||
|
Print (L"Entry %x = %x\n", Index, EntryValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
138
FatPkg/EnhancedFatDxe/Delete.c
Normal file
138
FatPkg/EnhancedFatDxe/Delete.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
delete.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Function that deletes a file
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatDelete (
|
||||||
|
IN EFI_FILE *FHand
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Deletes the file & Closes the file handle.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - Handle to the file to delete.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Delete the file successfully.
|
||||||
|
EFI_WARN_DELETE_FAILURE - Fail to delete the file.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
FAT_DIRENT *DirEnt;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Round;
|
||||||
|
|
||||||
|
IFile = IFILE_FROM_FHAND (FHand);
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lock the volume
|
||||||
|
//
|
||||||
|
FatAcquireLock ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the file is read-only, then don't delete it
|
||||||
|
//
|
||||||
|
if (IFile->ReadOnly) {
|
||||||
|
Status = EFI_WRITE_PROTECTED;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the file is the root dir, then don't delete it
|
||||||
|
//
|
||||||
|
if (OFile->Parent == NULL) {
|
||||||
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the file has a permanant error, skip the delete
|
||||||
|
//
|
||||||
|
Status = OFile->Error;
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// If this is a directory, make sure it's empty before
|
||||||
|
// allowing it to be deleted
|
||||||
|
//
|
||||||
|
if (OFile->ODir != NULL) {
|
||||||
|
//
|
||||||
|
// We do not allow to delete nonempty directory
|
||||||
|
//
|
||||||
|
FatResetODirCursor (OFile);
|
||||||
|
for (Round = 0; Round < 3; Round++) {
|
||||||
|
Status = FatGetNextDirEnt (OFile, &DirEnt);
|
||||||
|
if ((EFI_ERROR (Status)) ||
|
||||||
|
((Round < 2) && (DirEnt == NULL || !FatIsDotDirEnt (DirEnt))) ||
|
||||||
|
((Round == 2) && (DirEnt != NULL))
|
||||||
|
) {
|
||||||
|
Status = EFI_ACCESS_DENIED;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Return the file's space by setting its size to 0
|
||||||
|
//
|
||||||
|
FatTruncateOFile (OFile, 0);
|
||||||
|
//
|
||||||
|
// Free the directory entry for this file
|
||||||
|
//
|
||||||
|
Status = FatRemoveDirEnt (OFile->Parent, OFile->DirEnt);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Set a permanent error for this OFile in case there
|
||||||
|
// are still opened IFiles attached
|
||||||
|
//
|
||||||
|
OFile->Error = EFI_NOT_FOUND;
|
||||||
|
} else if (OFile->Error == EFI_NOT_FOUND) {
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
//
|
||||||
|
// Always close the handle
|
||||||
|
//
|
||||||
|
FatIFileClose (IFile);
|
||||||
|
//
|
||||||
|
// Done
|
||||||
|
//
|
||||||
|
Status = FatCleanupVolume (OFile->Volume, NULL, Status);
|
||||||
|
FatReleaseLock ();
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = EFI_WARN_DELETE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
238
FatPkg/EnhancedFatDxe/DirectoryCache.c
Normal file
238
FatPkg/EnhancedFatDxe/DirectoryCache.c
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
DirectoryCache.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Functions for directory cache operation
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
FatFreeODir (
|
||||||
|
IN FAT_ODIR *ODir
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Free the directory structure and release the memory.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ODir - The directory to be freed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_DIRENT *DirEnt;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Release Directory Entry Nodes
|
||||||
|
//
|
||||||
|
while (!IsListEmpty (&ODir->ChildList)) {
|
||||||
|
DirEnt = DIRENT_FROM_LINK (ODir->ChildList.ForwardLink);
|
||||||
|
RemoveEntryList (&DirEnt->Link);
|
||||||
|
//
|
||||||
|
// Make sure the OFile has been closed
|
||||||
|
//
|
||||||
|
ASSERT (DirEnt->OFile == NULL);
|
||||||
|
FatFreeDirEnt (DirEnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (ODir);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
FAT_ODIR *
|
||||||
|
FatAllocateODir (
|
||||||
|
IN FAT_OFILE *OFile
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Allocate the directory structure.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The corresponding OFile.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_ODIR *ODir;
|
||||||
|
|
||||||
|
ODir = AllocateZeroPool (sizeof (FAT_ODIR));
|
||||||
|
if (ODir != NULL) {
|
||||||
|
//
|
||||||
|
// Initialize the directory entry list
|
||||||
|
//
|
||||||
|
ODir->Signature = FAT_ODIR_SIGNATURE;
|
||||||
|
InitializeListHead (&ODir->ChildList);
|
||||||
|
ODir->CurrentCursor = &ODir->ChildList;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ODir;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatDiscardODir (
|
||||||
|
IN FAT_OFILE *OFile
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Discard the directory structure when an OFile will be freed.
|
||||||
|
Volume will cache this directory if the OFile does not represent a deleted file.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The OFile whose directory structure is to be discarded.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_ODIR *ODir;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
ODir = OFile->ODir;
|
||||||
|
if (!OFile->DirEnt->Invalid) {
|
||||||
|
//
|
||||||
|
// If OFile does not represent a deleted file, then we will cache the directory
|
||||||
|
// We use OFile's first cluster as the directory's tag
|
||||||
|
//
|
||||||
|
ODir->DirCacheTag = OFile->FileCluster;
|
||||||
|
InsertHeadList (&Volume->DirCacheList, &ODir->DirCacheLink);
|
||||||
|
if (Volume->DirCacheCount == FAT_MAX_DIR_CACHE_COUNT) {
|
||||||
|
//
|
||||||
|
// Replace the least recent used directory
|
||||||
|
//
|
||||||
|
ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
|
||||||
|
RemoveEntryList (&ODir->DirCacheLink);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// No need to find a replace
|
||||||
|
//
|
||||||
|
Volume->DirCacheCount++;
|
||||||
|
ODir = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Release ODir Structure
|
||||||
|
//
|
||||||
|
if (ODir != NULL) {
|
||||||
|
FatFreeODir (ODir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatRequestODir (
|
||||||
|
IN FAT_OFILE *OFile
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Request the directory structure when an OFile is newly generated.
|
||||||
|
If the directory structure is cached by volume, then just return this directory;
|
||||||
|
Otherwise, allocate a new one for OFile.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The OFile which requests directory structure.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN DirCacheTag;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
FAT_ODIR *ODir;
|
||||||
|
FAT_ODIR *CurrentODir;
|
||||||
|
LIST_ENTRY *CurrentODirLink;
|
||||||
|
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
ODir = NULL;
|
||||||
|
DirCacheTag = OFile->FileCluster;
|
||||||
|
for (CurrentODirLink = Volume->DirCacheList.ForwardLink;
|
||||||
|
CurrentODirLink != &Volume->DirCacheList;
|
||||||
|
CurrentODirLink = CurrentODirLink->ForwardLink
|
||||||
|
) {
|
||||||
|
CurrentODir = ODIR_FROM_DIRCACHELINK (CurrentODirLink);
|
||||||
|
if (CurrentODir->DirCacheTag == DirCacheTag) {
|
||||||
|
RemoveEntryList (&CurrentODir->DirCacheLink);
|
||||||
|
Volume->DirCacheCount--;
|
||||||
|
ODir = CurrentODir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ODir == NULL) {
|
||||||
|
//
|
||||||
|
// This directory is not cached, then allocate a new one
|
||||||
|
//
|
||||||
|
ODir = FatAllocateODir (OFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile->ODir = ODir;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatCleanupODirCache (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Clean up all the cached directory structures when the volume is going to be abandoned.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_ODIR *ODir;
|
||||||
|
while (Volume->DirCacheCount > 0) {
|
||||||
|
ODir = ODIR_FROM_DIRCACHELINK (Volume->DirCacheList.BackLink);
|
||||||
|
RemoveEntryList (&ODir->DirCacheLink);
|
||||||
|
FatFreeODir (ODir);
|
||||||
|
Volume->DirCacheCount--;
|
||||||
|
}
|
||||||
|
}
|
1563
FatPkg/EnhancedFatDxe/DirectoryManage.c
Normal file
1563
FatPkg/EnhancedFatDxe/DirectoryManage.c
Normal file
File diff suppressed because it is too large
Load Diff
541
FatPkg/EnhancedFatDxe/DiskCache.c
Normal file
541
FatPkg/EnhancedFatDxe/DiskCache.c
Normal file
@ -0,0 +1,541 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
DiskCache.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Cache implementation for EFI FAT File system driver
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
FatFlushDataCacheRange (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN IO_MODE IoMode,
|
||||||
|
IN UINTN StartPageNo,
|
||||||
|
IN UINTN EndPageNo,
|
||||||
|
OUT UINT8 *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This function is used by the Data Cache.
|
||||||
|
|
||||||
|
When this function is called by write command, all entries in this range
|
||||||
|
are older than the contents in disk, so they are invalid; just mark them invalid.
|
||||||
|
|
||||||
|
When this function is called by read command, if any entry in this range
|
||||||
|
is dirty, it means that the relative info directly readed from media is older than
|
||||||
|
than the info in the cache; So need to update the relative info in the Buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
IoMode - This function is called by read command or write command
|
||||||
|
StartPageNo - First PageNo to be checked in the cache.
|
||||||
|
EndPageNo - Last PageNo to be checked in the cache.
|
||||||
|
Buffer - The user buffer need to update. Only when doing the read command
|
||||||
|
and there is dirty cache in the cache range, this parameter will be used.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN PageNo;
|
||||||
|
UINTN GroupNo;
|
||||||
|
UINTN GroupMask;
|
||||||
|
UINTN PageSize;
|
||||||
|
UINT8 PageAlignment;
|
||||||
|
DISK_CACHE *DiskCache;
|
||||||
|
CACHE_TAG *CacheTag;
|
||||||
|
UINT8 *BaseAddress;
|
||||||
|
|
||||||
|
DiskCache = &Volume->DiskCache[CACHE_DATA];
|
||||||
|
BaseAddress = DiskCache->CacheBase;
|
||||||
|
GroupMask = DiskCache->GroupMask;
|
||||||
|
PageAlignment = DiskCache->PageAlignment;
|
||||||
|
PageSize = (UINTN)1 << PageAlignment;
|
||||||
|
|
||||||
|
for (PageNo = StartPageNo; PageNo < EndPageNo; PageNo++) {
|
||||||
|
GroupNo = PageNo & GroupMask;
|
||||||
|
CacheTag = &DiskCache->CacheTag[GroupNo];
|
||||||
|
if (CacheTag->RealSize > 0 && CacheTag->PageNo == PageNo) {
|
||||||
|
//
|
||||||
|
// When reading data form disk directly, if some dirty data
|
||||||
|
// in cache is in this rang, this data in the Buffer need to
|
||||||
|
// be updated with the cache's dirty data.
|
||||||
|
//
|
||||||
|
if (IoMode == READ_DISK) {
|
||||||
|
if (CacheTag->Dirty) {
|
||||||
|
CopyMem (
|
||||||
|
Buffer + ((PageNo - StartPageNo) << PageAlignment),
|
||||||
|
BaseAddress + (GroupNo << PageAlignment),
|
||||||
|
PageSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Make all valid entries in this range invalid.
|
||||||
|
//
|
||||||
|
CacheTag->RealSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
FatExchangeCachePage (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN CACHE_DATA_TYPE DataType,
|
||||||
|
IN IO_MODE IoMode,
|
||||||
|
IN CACHE_TAG *CacheTag
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Exchange the cache page with the image on the disk
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
DataType - Indicate the cache type.
|
||||||
|
IoMode - Indicate whether to load this page from disk or store this page to disk.
|
||||||
|
CacheTag - The Cache Tag for the current cache page.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Cache page exchanged successfully.
|
||||||
|
Others - An error occurred when exchanging cache page.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN GroupNo;
|
||||||
|
UINTN PageNo;
|
||||||
|
UINTN WriteCount;
|
||||||
|
UINTN RealSize;
|
||||||
|
UINT64 EntryPos;
|
||||||
|
UINT64 MaxSize;
|
||||||
|
DISK_CACHE *DiskCache;
|
||||||
|
VOID *PageAddress;
|
||||||
|
UINT8 PageAlignment;
|
||||||
|
|
||||||
|
DiskCache = &Volume->DiskCache[DataType];
|
||||||
|
PageNo = CacheTag->PageNo;
|
||||||
|
GroupNo = PageNo & DiskCache->GroupMask;
|
||||||
|
PageAlignment = DiskCache->PageAlignment;
|
||||||
|
PageAddress = DiskCache->CacheBase + (GroupNo << PageAlignment);
|
||||||
|
EntryPos = DiskCache->BaseAddress + LShiftU64 (PageNo, PageAlignment);
|
||||||
|
RealSize = CacheTag->RealSize;
|
||||||
|
if (IoMode == READ_DISK) {
|
||||||
|
RealSize = (UINTN)1 << PageAlignment;
|
||||||
|
MaxSize = DiskCache->LimitAddress - EntryPos;
|
||||||
|
if (MaxSize < RealSize) {
|
||||||
|
DEBUG ((EFI_D_INFO, "FatDiskIo: Cache Page OutBound occurred! \n"));
|
||||||
|
RealSize = (UINTN) MaxSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteCount = 1;
|
||||||
|
if (DataType == CACHE_FAT && IoMode == WRITE_DISK) {
|
||||||
|
WriteCount = Volume->NumFats;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
//
|
||||||
|
// Only fat table writing will execute more than once
|
||||||
|
//
|
||||||
|
Status = FatDiskIo (Volume, IoMode, EntryPos, RealSize, PageAddress);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntryPos += Volume->FatSize;
|
||||||
|
} while (--WriteCount > 0);
|
||||||
|
|
||||||
|
CacheTag->Dirty = FALSE;
|
||||||
|
CacheTag->RealSize = RealSize;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetCachePage (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN CACHE_DATA_TYPE CacheDataType,
|
||||||
|
IN UINTN PageNo,
|
||||||
|
IN CACHE_TAG *CacheTag
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get one cache page by specified PageNo.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
CacheDataType - The cache type: CACHE_FAT or CACHE_DATA.
|
||||||
|
PageNo - PageNo to match with the cache.
|
||||||
|
CacheTag - The Cache Tag for the current cache page.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the cache page successfully.
|
||||||
|
other - An error occurred when accessing data.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN OldPageNo;
|
||||||
|
|
||||||
|
OldPageNo = CacheTag->PageNo;
|
||||||
|
if (CacheTag->RealSize > 0 && OldPageNo == PageNo) {
|
||||||
|
//
|
||||||
|
// Cache Hit occurred
|
||||||
|
//
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write dirty cache page back to disk
|
||||||
|
//
|
||||||
|
if (CacheTag->RealSize > 0 && CacheTag->Dirty) {
|
||||||
|
Status = FatExchangeCachePage (Volume, CacheDataType, WRITE_DISK, CacheTag);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Load new data from disk;
|
||||||
|
//
|
||||||
|
CacheTag->PageNo = PageNo;
|
||||||
|
Status = FatExchangeCachePage (Volume, CacheDataType, READ_DISK, CacheTag);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
FatAccessUnalignedCachePage (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN CACHE_DATA_TYPE CacheDataType,
|
||||||
|
IN IO_MODE IoMode,
|
||||||
|
IN UINTN PageNo,
|
||||||
|
IN UINTN Offset,
|
||||||
|
IN UINTN Length,
|
||||||
|
IN OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Read Length bytes from the position of Offset into Buffer, or
|
||||||
|
write Length bytes from Buffer into the position of Offset.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
CacheDataType - The type of cache: CACHE_DATA or CACHE_FAT.
|
||||||
|
IoMode - Indicate the type of disk access.
|
||||||
|
PageNo - The number of unaligned cache page.
|
||||||
|
Offset - The starting byte of cache page.
|
||||||
|
Length - The number of bytes that is read or written
|
||||||
|
Buffer - Buffer containing cache data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The data was accessed correctly.
|
||||||
|
Others - An error occurred when accessing unaligned cache page.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
VOID *Source;
|
||||||
|
VOID *Destination;
|
||||||
|
DISK_CACHE *DiskCache;
|
||||||
|
CACHE_TAG *CacheTag;
|
||||||
|
UINTN GroupNo;
|
||||||
|
|
||||||
|
DiskCache = &Volume->DiskCache[CacheDataType];
|
||||||
|
GroupNo = PageNo & DiskCache->GroupMask;
|
||||||
|
CacheTag = &DiskCache->CacheTag[GroupNo];
|
||||||
|
Status = FatGetCachePage (Volume, CacheDataType, PageNo, CacheTag);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Source = DiskCache->CacheBase + (GroupNo << DiskCache->PageAlignment) + Offset;
|
||||||
|
Destination = Buffer;
|
||||||
|
if (IoMode != READ_DISK) {
|
||||||
|
CacheTag->Dirty = TRUE;
|
||||||
|
DiskCache->Dirty = TRUE;
|
||||||
|
Destination = Source;
|
||||||
|
Source = Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyMem (Destination, Source, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatAccessCache (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN CACHE_DATA_TYPE CacheDataType,
|
||||||
|
IN IO_MODE IoMode,
|
||||||
|
IN UINT64 Offset,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN OUT UINT8 *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Read BufferSize bytes from the position of Offset into Buffer,
|
||||||
|
or write BufferSize bytes from Buffer into the position of Offset.
|
||||||
|
|
||||||
|
Base on the parameter of CACHE_DATA_TYPE, the data access will be divided into
|
||||||
|
the access of FAT cache (CACHE_FAT) and the access of Data cache (CACHE_DATA):
|
||||||
|
|
||||||
|
1. Access of FAT cache (CACHE_FAT): Access the data in the FAT cache, if there is cache
|
||||||
|
page hit, just return the cache page; else update the related cache page and return
|
||||||
|
the right cache page.
|
||||||
|
2. Access of Data cache (CACHE_DATA):
|
||||||
|
The access data will be divided into UnderRun data, Aligned data and OverRun data;
|
||||||
|
The UnderRun data and OverRun data will be accessed by the Data cache,
|
||||||
|
but the Aligned data will be accessed with disk directly.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
CacheDataType - The type of cache: CACHE_DATA or CACHE_FAT.
|
||||||
|
IoMode - Indicate the type of disk access.
|
||||||
|
Offset - The starting byte offset to read from.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing cache data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The data was accessed correctly.
|
||||||
|
EFI_MEDIA_CHANGED - The MediaId does not match the current device.
|
||||||
|
Others - An error occurred when accessing cache.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN PageSize;
|
||||||
|
UINTN UnderRun;
|
||||||
|
UINTN OverRun;
|
||||||
|
UINTN AlignedSize;
|
||||||
|
UINTN Length;
|
||||||
|
UINTN PageNo;
|
||||||
|
UINTN AlignedPageCount;
|
||||||
|
UINTN OverRunPageNo;
|
||||||
|
DISK_CACHE *DiskCache;
|
||||||
|
UINT64 EntryPos;
|
||||||
|
UINT8 PageAlignment;
|
||||||
|
|
||||||
|
ASSERT (Volume->CacheBuffer != NULL);
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
DiskCache = &Volume->DiskCache[CacheDataType];
|
||||||
|
EntryPos = Offset - DiskCache->BaseAddress;
|
||||||
|
PageAlignment = DiskCache->PageAlignment;
|
||||||
|
PageSize = (UINTN)1 << PageAlignment;
|
||||||
|
PageNo = (UINTN) RShiftU64 (EntryPos, PageAlignment);
|
||||||
|
UnderRun = ((UINTN) EntryPos) & (PageSize - 1);
|
||||||
|
|
||||||
|
if (UnderRun > 0) {
|
||||||
|
Length = PageSize - UnderRun;
|
||||||
|
if (Length > BufferSize) {
|
||||||
|
Length = BufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatAccessUnalignedCachePage (Volume, CacheDataType, IoMode, PageNo, UnderRun, Length, Buffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer += Length;
|
||||||
|
BufferSize -= Length;
|
||||||
|
PageNo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
AlignedPageCount = BufferSize >> PageAlignment;
|
||||||
|
OverRunPageNo = PageNo + AlignedPageCount;
|
||||||
|
//
|
||||||
|
// The access of the Aligned data
|
||||||
|
//
|
||||||
|
if (AlignedPageCount > 0) {
|
||||||
|
//
|
||||||
|
// Accessing fat table cannot have alignment data
|
||||||
|
//
|
||||||
|
ASSERT (CacheDataType == CACHE_DATA);
|
||||||
|
|
||||||
|
EntryPos = Volume->RootPos + LShiftU64 (PageNo, PageAlignment);
|
||||||
|
AlignedSize = AlignedPageCount << PageAlignment;
|
||||||
|
Status = FatDiskIo (Volume, IoMode, EntryPos, AlignedSize, Buffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If these access data over laps the relative cache range, these cache pages need
|
||||||
|
// to be updated.
|
||||||
|
//
|
||||||
|
FatFlushDataCacheRange (Volume, IoMode, PageNo, OverRunPageNo, Buffer);
|
||||||
|
Buffer += AlignedSize;
|
||||||
|
BufferSize -= AlignedSize;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// The access of the OverRun data
|
||||||
|
//
|
||||||
|
OverRun = BufferSize;
|
||||||
|
if (OverRun > 0) {
|
||||||
|
//
|
||||||
|
// Last read is not a complete page
|
||||||
|
//
|
||||||
|
Status = FatAccessUnalignedCachePage (Volume, CacheDataType, IoMode, OverRunPageNo, 0, OverRun, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatVolumeFlushCache (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Flush all the dirty cache back, include the FAT cache and the Data cache.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Flush all the dirty cache back successfully
|
||||||
|
other - An error occurred when writing the data into the disk
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
CACHE_DATA_TYPE CacheDataType;
|
||||||
|
UINTN GroupIndex;
|
||||||
|
UINTN GroupMask;
|
||||||
|
DISK_CACHE *DiskCache;
|
||||||
|
CACHE_TAG *CacheTag;
|
||||||
|
|
||||||
|
for (CacheDataType = (CACHE_DATA_TYPE) 0; CacheDataType < CACHE_MAX_TYPE; CacheDataType++) {
|
||||||
|
DiskCache = &Volume->DiskCache[CacheDataType];
|
||||||
|
if (DiskCache->Dirty) {
|
||||||
|
//
|
||||||
|
// Data cache or fat cache is dirty, write the dirty data back
|
||||||
|
//
|
||||||
|
GroupMask = DiskCache->GroupMask;
|
||||||
|
for (GroupIndex = 0; GroupIndex <= GroupMask; GroupIndex++) {
|
||||||
|
CacheTag = &DiskCache->CacheTag[GroupIndex];
|
||||||
|
if (CacheTag->RealSize > 0 && CacheTag->Dirty) {
|
||||||
|
//
|
||||||
|
// Write back all Dirty Data Cache Page to disk
|
||||||
|
//
|
||||||
|
Status = FatExchangeCachePage (Volume, CacheDataType, WRITE_DISK, CacheTag);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DiskCache->Dirty = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Flush the block device.
|
||||||
|
//
|
||||||
|
Status = Volume->BlockIo->FlushBlocks (Volume->BlockIo);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatInitializeDiskCache (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Initialize the disk cache according to Volume's FatType.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The disk cache is successfully initialized.
|
||||||
|
EFI_OUT_OF_RESOURCES - Not enough memory to allocate disk cache.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
DISK_CACHE *DiskCache;
|
||||||
|
UINTN FatCacheGroupCount;
|
||||||
|
UINTN DataCacheSize;
|
||||||
|
UINTN FatCacheSize;
|
||||||
|
UINT8 *CacheBuffer;
|
||||||
|
|
||||||
|
DiskCache = Volume->DiskCache;
|
||||||
|
//
|
||||||
|
// Configure the parameters of disk cache
|
||||||
|
//
|
||||||
|
if (Volume->FatType == FAT12) {
|
||||||
|
FatCacheGroupCount = FAT_FATCACHE_GROUP_MIN_COUNT;
|
||||||
|
DiskCache[CACHE_FAT].PageAlignment = FAT_FATCACHE_PAGE_MIN_ALIGNMENT;
|
||||||
|
DiskCache[CACHE_DATA].PageAlignment = FAT_DATACACHE_PAGE_MIN_ALIGNMENT;
|
||||||
|
} else {
|
||||||
|
FatCacheGroupCount = FAT_FATCACHE_GROUP_MAX_COUNT;
|
||||||
|
DiskCache[CACHE_FAT].PageAlignment = FAT_FATCACHE_PAGE_MAX_ALIGNMENT;
|
||||||
|
DiskCache[CACHE_DATA].PageAlignment = FAT_DATACACHE_PAGE_MAX_ALIGNMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiskCache[CACHE_DATA].GroupMask = FAT_DATACACHE_GROUP_COUNT - 1;
|
||||||
|
DiskCache[CACHE_DATA].BaseAddress = Volume->RootPos;
|
||||||
|
DiskCache[CACHE_DATA].LimitAddress = Volume->VolumeSize;
|
||||||
|
DiskCache[CACHE_FAT].GroupMask = FatCacheGroupCount - 1;
|
||||||
|
DiskCache[CACHE_FAT].BaseAddress = Volume->FatPos;
|
||||||
|
DiskCache[CACHE_FAT].LimitAddress = Volume->FatPos + Volume->FatSize;
|
||||||
|
FatCacheSize = FatCacheGroupCount << DiskCache[CACHE_FAT].PageAlignment;
|
||||||
|
DataCacheSize = FAT_DATACACHE_GROUP_COUNT << DiskCache[CACHE_DATA].PageAlignment;
|
||||||
|
//
|
||||||
|
// Allocate the Fat Cache buffer
|
||||||
|
//
|
||||||
|
CacheBuffer = AllocatePool (FatCacheSize + DataCacheSize);
|
||||||
|
if (CacheBuffer == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volume->CacheBuffer = CacheBuffer;
|
||||||
|
DiskCache[CACHE_FAT].CacheBase = CacheBuffer;
|
||||||
|
DiskCache[CACHE_DATA].CacheBase = CacheBuffer + FatCacheSize;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
393
FatPkg/EnhancedFatDxe/Fat.c
Normal file
393
FatPkg/EnhancedFatDxe/Fat.c
Normal file
@ -0,0 +1,393 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
Fat.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Fat File System driver routines that support EFI driver model
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatEntryPoint (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatUnload (
|
||||||
|
IN EFI_HANDLE ImageHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatDriverBindingSupported (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatDriverBindingStart (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatDriverBindingStop (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE Controller,
|
||||||
|
IN UINTN NumberOfChildren,
|
||||||
|
IN EFI_HANDLE *ChildHandleBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// DriverBinding protocol instance
|
||||||
|
//
|
||||||
|
EFI_DRIVER_BINDING_PROTOCOL gFatDriverBinding = {
|
||||||
|
FatDriverBindingSupported,
|
||||||
|
FatDriverBindingStart,
|
||||||
|
FatDriverBindingStop,
|
||||||
|
0xa,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatEntryPoint (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Register Driver Binding protocol for this driver.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ImageHandle - Handle for the image of this driver.
|
||||||
|
SystemTable - Pointer to the EFI System Table.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Driver loaded.
|
||||||
|
other - Driver not loaded.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the EFI Driver Library
|
||||||
|
//
|
||||||
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
||||||
|
ImageHandle,
|
||||||
|
SystemTable,
|
||||||
|
&gFatDriverBinding,
|
||||||
|
ImageHandle,
|
||||||
|
&gFatComponentName,
|
||||||
|
&gFatComponentName2
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatUnload (
|
||||||
|
IN EFI_HANDLE ImageHandle
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Unload function for this image. Uninstall DriverBinding protocol.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ImageHandle - Handle for the image of this driver.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Driver unloaded successfully.
|
||||||
|
other - Driver can not unloaded.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_HANDLE *DeviceHandleBuffer;
|
||||||
|
UINTN DeviceHandleCount;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
AllHandles,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&DeviceHandleCount,
|
||||||
|
&DeviceHandleBuffer
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
for (Index = 0; Index < DeviceHandleCount; Index++) {
|
||||||
|
Status = gBS->DisconnectController (
|
||||||
|
DeviceHandleBuffer[Index],
|
||||||
|
ImageHandle,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceHandleBuffer != NULL) {
|
||||||
|
FreePool (DeviceHandleBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatDriverBindingSupported (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE ControllerHandle,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Test to see if this driver can add a file system to ControllerHandle.
|
||||||
|
ControllerHandle must support both Disk IO and Block IO protocols.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
This - Protocol instance pointer.
|
||||||
|
ControllerHandle - Handle of device to test.
|
||||||
|
RemainingDevicePath - Not used.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - This driver supports this device.
|
||||||
|
EFI_ALREADY_STARTED - This driver is already running on this device.
|
||||||
|
other - This driver does not support this device.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open the IO Abstraction(s) needed to perform the supported test
|
||||||
|
//
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiDiskIoProtocolGuid,
|
||||||
|
(VOID **) &DiskIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle,
|
||||||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Close the I/O Abstraction(s) used to perform the supported test
|
||||||
|
//
|
||||||
|
gBS->CloseProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiDiskIoProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open the IO Abstraction(s) needed to perform the supported test
|
||||||
|
//
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiBlockIoProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle,
|
||||||
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||||
|
);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatDriverBindingStart (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE ControllerHandle,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Start this driver on ControllerHandle by opening a Block IO and Disk IO
|
||||||
|
protocol, reading Device Path. Add a Simple File System protocol to
|
||||||
|
ControllerHandle if the media contains a valid file system.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
This - Protocol instance pointer.
|
||||||
|
ControllerHandle - Handle of device to bind driver to.
|
||||||
|
RemainingDevicePath - Not used.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - This driver is added to DeviceHandle.
|
||||||
|
EFI_ALREADY_STARTED - This driver is already running on DeviceHandle.
|
||||||
|
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
|
||||||
|
other - This driver does not support this device.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||||
|
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||||
|
|
||||||
|
Status = InitializeUnicodeCollationSupport (This->DriverBindingHandle);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Open our required BlockIo and DiskIo
|
||||||
|
//
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiBlockIoProtocolGuid,
|
||||||
|
(VOID **) &BlockIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle,
|
||||||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiDiskIoProtocolGuid,
|
||||||
|
(VOID **) &DiskIo,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle,
|
||||||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Allocate Volume structure. In FatAllocateVolume(), Resources
|
||||||
|
// are allocated with protocol installed and cached initialized
|
||||||
|
//
|
||||||
|
Status = FatAllocateVolume (ControllerHandle, DiskIo, BlockIo);
|
||||||
|
|
||||||
|
//
|
||||||
|
// When the media changes on a device it will Reinstall the BlockIo interaface.
|
||||||
|
// This will cause a call to our Stop(), and a subsequent reentrant call to our
|
||||||
|
// Start() successfully. We should leave the device open when this happen.
|
||||||
|
//
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiSimpleFileSystemProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle,
|
||||||
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
gBS->CloseProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiDiskIoProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatDriverBindingStop (
|
||||||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||||
|
IN EFI_HANDLE ControllerHandle,
|
||||||
|
IN UINTN NumberOfChildren,
|
||||||
|
IN EFI_HANDLE *ChildHandleBuffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
Stop this driver on ControllerHandle.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
This - Protocol instance pointer.
|
||||||
|
ControllerHandle - Handle of device to stop driver on.
|
||||||
|
NumberOfChildren - Not used.
|
||||||
|
ChildHandleBuffer - Not used.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
EFI_SUCCESS - This driver is removed DeviceHandle.
|
||||||
|
other - This driver was not removed from this device.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get our context back
|
||||||
|
//
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiSimpleFileSystemProtocolGuid,
|
||||||
|
(VOID **) &FileSystem,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle,
|
||||||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Volume = VOLUME_FROM_VOL_INTERFACE (FileSystem);
|
||||||
|
Status = FatAbandonVolume (Volume);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->CloseProtocol (
|
||||||
|
ControllerHandle,
|
||||||
|
&gEfiDiskIoProtocolGuid,
|
||||||
|
This->DriverBindingHandle,
|
||||||
|
ControllerHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
1119
FatPkg/EnhancedFatDxe/Fat.h
Normal file
1119
FatPkg/EnhancedFatDxe/Fat.h
Normal file
File diff suppressed because it is too large
Load Diff
98
FatPkg/EnhancedFatDxe/Fat.inf
Normal file
98
FatPkg/EnhancedFatDxe/Fat.inf
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#/** @file
|
||||||
|
# Component description file for FAT module.
|
||||||
|
#
|
||||||
|
# This UEFI driver detects the FAT file system in the disk.
|
||||||
|
# It also produces the Simple File System protocol for the consumer to
|
||||||
|
# perform file and directory operations on the disk.
|
||||||
|
# Copyright (c) 2007, Intel Corporation
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials are licensed and made available
|
||||||
|
# under the terms and conditions of the BSD License which accompanies this
|
||||||
|
# distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#**/
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = Fat
|
||||||
|
FILE_GUID = 961578FE-B6B7-44c3-AF35-6BC705CD2B1F
|
||||||
|
MODULE_TYPE = UEFI_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
EDK_RELEASE_VERSION = 0x00020000
|
||||||
|
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||||
|
|
||||||
|
ENTRY_POINT = FatEntryPoint
|
||||||
|
UNLOAD_IMAGE = FatUnload
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||||
|
#
|
||||||
|
# DRIVER_BINDING = gFatDriverBinding
|
||||||
|
# COMPONENT_NAME = gFatComponentName
|
||||||
|
# COMPONENT_NAME2 = gFatComponentName2
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources.common]
|
||||||
|
DirectoryCache.c
|
||||||
|
DiskCache.c
|
||||||
|
FileName.c
|
||||||
|
Hash.c
|
||||||
|
DirectoryManage.c
|
||||||
|
ComponentName.c
|
||||||
|
FatFileSystem.h
|
||||||
|
Fat.h
|
||||||
|
ReadWrite.c
|
||||||
|
OpenVolume.c
|
||||||
|
Open.c
|
||||||
|
Misc.c
|
||||||
|
Init.c
|
||||||
|
Info.c
|
||||||
|
FileSpace.c
|
||||||
|
Flush.c
|
||||||
|
Fat.c
|
||||||
|
Delete.c
|
||||||
|
Data.c
|
||||||
|
UnicodeCollation.c
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
FatPkg/FatPkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
UefiRuntimeServicesTableLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
BaseMemoryLib
|
||||||
|
BaseLib
|
||||||
|
UefiLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
DebugLib
|
||||||
|
PcdLib
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiFileInfoGuid
|
||||||
|
gEfiFileSystemInfoGuid
|
||||||
|
gEfiFileSystemVolumeLabelInfoIdGuid
|
||||||
|
gEfiGlobalVariableGuid
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiDiskIoProtocolGuid
|
||||||
|
gEfiBlockIoProtocolGuid
|
||||||
|
gEfiSimpleFileSystemProtocolGuid
|
||||||
|
gEfiUnicodeCollationProtocolGuid
|
||||||
|
gEfiUnicodeCollation2ProtocolGuid
|
||||||
|
|
||||||
|
[FeaturePcd]
|
||||||
|
gEfiFatPkgTokenSpaceGuid.PcdUnicodeCollationSupport
|
||||||
|
gEfiFatPkgTokenSpaceGuid.PcdUnicodeCollation2Support
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang
|
||||||
|
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang
|
221
FatPkg/EnhancedFatDxe/FatFileSystem.h
Normal file
221
FatPkg/EnhancedFatDxe/FatFileSystem.h
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
FatFileSystem.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Definitions for on-disk FAT structures
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#ifndef _FATFILESYSTEM_H_
|
||||||
|
#define _FATFILESYSTEM_H_
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
//
|
||||||
|
// FAT info signature
|
||||||
|
//
|
||||||
|
#define FAT_INFO_SIGNATURE 0x41615252
|
||||||
|
#define FAT_INFO_BEGIN_SIGNATURE 0x61417272
|
||||||
|
#define FAT_INFO_END_SIGNATURE 0xAA550000
|
||||||
|
//
|
||||||
|
// FAT entry values
|
||||||
|
//
|
||||||
|
#define FAT_CLUSTER_SPECIAL_EXT (-1 & (~0xF))
|
||||||
|
#define FAT_CLUSTER_SPECIAL ((FAT_CLUSTER_SPECIAL_EXT) | 0x07)
|
||||||
|
#define FAT_CLUSTER_FREE 0
|
||||||
|
#define FAT_CLUSTER_RESERVED (FAT_CLUSTER_SPECIAL)
|
||||||
|
#define FAT_CLUSTER_BAD (FAT_CLUSTER_SPECIAL)
|
||||||
|
#define FAT_CLUSTER_LAST (-1)
|
||||||
|
#define FAT_END_OF_FAT_CHAIN(Cluster) ((Cluster) > (FAT_CLUSTER_SPECIAL))
|
||||||
|
#define FAT_MIN_CLUSTER 2
|
||||||
|
#define FAT_MAX_FAT12_CLUSTER 0xFF5
|
||||||
|
#define FAT_MAX_FAT16_CLUSTER 0xFFF5
|
||||||
|
#define FAT_CLUSTER_SPECIAL_FAT12 0xFF7
|
||||||
|
#define FAT_CLUSTER_SPECIAL_FAT16 0xFFF7
|
||||||
|
#define FAT_CLUSTER_SPECIAL_FAT32 0x0FFFFFF7
|
||||||
|
#define FAT_CLUSTER_MASK_FAT12 0xFFF
|
||||||
|
#define FAT_CLUSTER_UNMASK_FAT12 0xF000
|
||||||
|
#define FAT_CLUSTER_MASK_FAT32 0x0FFFFFFF
|
||||||
|
#define FAT_CLUSTER_UNMASK_FAT32 0xF0000000
|
||||||
|
#define FAT_POS_FAT12(a) ((a) * 3 / 2)
|
||||||
|
#define FAT_POS_FAT16(a) ((a) * 2)
|
||||||
|
#define FAT_POS_FAT32(a) ((a) * 4)
|
||||||
|
#define FAT_ODD_CLUSTER_FAT12(a) (((a) & 1) != 0)
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// FAT attribute define
|
||||||
|
//
|
||||||
|
#define FAT_ATTRIBUTE_READ_ONLY 0x01
|
||||||
|
#define FAT_ATTRIBUTE_HIDDEN 0x02
|
||||||
|
#define FAT_ATTRIBUTE_SYSTEM 0x04
|
||||||
|
#define FAT_ATTRIBUTE_VOLUME_ID 0x08
|
||||||
|
#define FAT_ATTRIBUTE_DIRECTORY 0x10
|
||||||
|
#define FAT_ATTRIBUTE_ARCHIVE 0x20
|
||||||
|
#define FAT_ATTRIBUTE_DEVICE 0x40
|
||||||
|
#define FAT_ATTRIBUTE_LFN 0x0F
|
||||||
|
//
|
||||||
|
// Some Long File Name definitions
|
||||||
|
//
|
||||||
|
#define FAT_LFN_LAST 0x40 // Ordinal field
|
||||||
|
#define MAX_LFN_ENTRIES 20
|
||||||
|
#define LFN_CHAR1_LEN 5
|
||||||
|
#define LFN_CHAR2_LEN 6
|
||||||
|
#define LFN_CHAR3_LEN 2
|
||||||
|
#define LFN_CHAR_TOTAL (LFN_CHAR1_LEN + LFN_CHAR2_LEN + LFN_CHAR3_LEN)
|
||||||
|
#define LFN_ENTRY_NUMBER(a) (((a) + LFN_CHAR_TOTAL - 1) / LFN_CHAR_TOTAL)
|
||||||
|
//
|
||||||
|
// Some 8.3 File Name definitions
|
||||||
|
//
|
||||||
|
#define FAT_MAIN_NAME_LEN 8
|
||||||
|
#define FAT_EXTEND_NAME_LEN 3
|
||||||
|
#define FAT_NAME_LEN (FAT_MAIN_NAME_LEN + FAT_EXTEND_NAME_LEN)
|
||||||
|
//
|
||||||
|
// Some directory entry information
|
||||||
|
//
|
||||||
|
#define FAT_ENTRY_INFO_OFFSET 13
|
||||||
|
#define DELETE_ENTRY_MARK 0xE5
|
||||||
|
#define EMPTY_ENTRY_MARK 0x00
|
||||||
|
|
||||||
|
//
|
||||||
|
// Volume dirty Mask
|
||||||
|
//
|
||||||
|
#define FAT16_DIRTY_MASK 0x7fff
|
||||||
|
#define FAT32_DIRTY_MASK 0xf7ffffff
|
||||||
|
//
|
||||||
|
// internal flag
|
||||||
|
//
|
||||||
|
#define FAT_CASE_MIXED 0x01
|
||||||
|
#define FAT_CASE_NAME_LOWER 0x08
|
||||||
|
#define FAT_CASE_EXT_LOWER 0x10
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Ia32Jump[3];
|
||||||
|
CHAR8 OemId[8];
|
||||||
|
UINT16 SectorSize;
|
||||||
|
UINT8 SectorsPerCluster;
|
||||||
|
UINT16 ReservedSectors;
|
||||||
|
UINT8 NumFats;
|
||||||
|
UINT16 RootEntries; // < FAT32, root dir is fixed size
|
||||||
|
UINT16 Sectors;
|
||||||
|
UINT8 Media;
|
||||||
|
UINT16 SectorsPerFat; // < FAT32
|
||||||
|
UINT16 SectorsPerTrack; // (ignored)
|
||||||
|
UINT16 Heads; // (ignored)
|
||||||
|
UINT32 HiddenSectors; // (ignored)
|
||||||
|
UINT32 LargeSectors; // Used if Sectors==0
|
||||||
|
} FAT_BOOT_SECTOR_BASIC;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 PhysicalDriveNumber; // (ignored)
|
||||||
|
UINT8 CurrentHead; // holds boot_sector_dirty bit
|
||||||
|
UINT8 Signature; // (ignored)
|
||||||
|
CHAR8 Id[4];
|
||||||
|
CHAR8 FatLabel[11];
|
||||||
|
CHAR8 SystemId[8];
|
||||||
|
} FAT_BOOT_SECTOR_EXT;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 LargeSectorsPerFat; // FAT32
|
||||||
|
UINT16 ExtendedFlags; // FAT32 (ignored)
|
||||||
|
UINT16 FsVersion; // FAT32 (ignored)
|
||||||
|
UINT32 RootDirFirstCluster; // FAT32
|
||||||
|
UINT16 FsInfoSector; // FAT32
|
||||||
|
UINT16 BackupBootSector; // FAT32
|
||||||
|
UINT8 Reserved[12]; // FAT32 (ignored)
|
||||||
|
UINT8 PhysicalDriveNumber; // (ignored)
|
||||||
|
UINT8 CurrentHead; // holds boot_sector_dirty bit
|
||||||
|
UINT8 Signature; // (ignored)
|
||||||
|
CHAR8 Id[4];
|
||||||
|
CHAR8 FatLabel[11];
|
||||||
|
CHAR8 SystemId[8];
|
||||||
|
} FAT32_BOOT_SECTOR_EXT;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FAT_BOOT_SECTOR_BASIC FatBsb;
|
||||||
|
union {
|
||||||
|
FAT_BOOT_SECTOR_EXT FatBse;
|
||||||
|
FAT32_BOOT_SECTOR_EXT Fat32Bse;
|
||||||
|
} FatBse;
|
||||||
|
} FAT_BOOT_SECTOR;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FAT Info Structure
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
UINT32 ClusterCount;
|
||||||
|
UINT32 NextCluster;
|
||||||
|
} FAT_FREE_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature;
|
||||||
|
UINT8 ExtraBootCode[480];
|
||||||
|
UINT32 InfoBeginSignature;
|
||||||
|
FAT_FREE_INFO FreeInfo;
|
||||||
|
UINT8 Reserved[12];
|
||||||
|
UINT32 InfoEndSignature;
|
||||||
|
} FAT_INFO_SECTOR;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Directory Entry
|
||||||
|
//
|
||||||
|
#define FAT_MAX_YEAR_FROM_1980 0x7f
|
||||||
|
typedef struct {
|
||||||
|
UINT16 Day : 5;
|
||||||
|
UINT16 Month : 4;
|
||||||
|
UINT16 Year : 7; // From 1980
|
||||||
|
} FAT_DATE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 DoubleSecond : 5;
|
||||||
|
UINT16 Minute : 6;
|
||||||
|
UINT16 Hour : 5;
|
||||||
|
} FAT_TIME;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FAT_TIME Time;
|
||||||
|
FAT_DATE Date;
|
||||||
|
} FAT_DATE_TIME;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CHAR8 FileName[11]; // 8.3 filename
|
||||||
|
UINT8 Attributes;
|
||||||
|
UINT8 CaseFlag;
|
||||||
|
UINT8 CreateMillisecond; // (creation milliseconds - ignored)
|
||||||
|
FAT_DATE_TIME FileCreateTime;
|
||||||
|
FAT_DATE FileLastAccess;
|
||||||
|
UINT16 FileClusterHigh; // >= FAT32
|
||||||
|
FAT_DATE_TIME FileModificationTime;
|
||||||
|
UINT16 FileCluster;
|
||||||
|
UINT32 FileSize;
|
||||||
|
} FAT_DIRECTORY_ENTRY;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Ordinal;
|
||||||
|
CHAR8 Name1[10]; // (Really 5 chars, but not WCHAR aligned)
|
||||||
|
UINT8 Attributes;
|
||||||
|
UINT8 Type;
|
||||||
|
UINT8 Checksum;
|
||||||
|
CHAR16 Name2[6];
|
||||||
|
UINT16 MustBeZero;
|
||||||
|
CHAR16 Name3[2];
|
||||||
|
} FAT_DIRECTORY_LFN;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
#endif
|
583
FatPkg/EnhancedFatDxe/FileName.c
Normal file
583
FatPkg/EnhancedFatDxe/FileName.c
Normal file
@ -0,0 +1,583 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
FileName.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Functions for manipulating file names
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
FatCheckIs8Dot3Name (
|
||||||
|
IN CHAR16 *FileName,
|
||||||
|
OUT CHAR8 *File8Dot3Name
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This function checks whether the input FileName is a valid 8.3 short name.
|
||||||
|
If the input FileName is a valid 8.3, the output is the 8.3 short name;
|
||||||
|
otherwise, the output is the base tag of 8.3 short name.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FileName - The input unicode filename.
|
||||||
|
File8Dot3Name - The output ascii 8.3 short name or base tag of 8.3 short name.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
TRUE - The input unicode filename is a valid 8.3 short name.
|
||||||
|
FALSE - The input unicode filename is not a valid 8.3 short name.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
BOOLEAN PossibleShortName;
|
||||||
|
CHAR16 *TempName;
|
||||||
|
CHAR16 *ExtendName;
|
||||||
|
CHAR16 *SeparateDot;
|
||||||
|
UINTN MainNameLen;
|
||||||
|
UINTN ExtendNameLen;
|
||||||
|
|
||||||
|
PossibleShortName = TRUE;
|
||||||
|
SeparateDot = NULL;
|
||||||
|
SetMem (File8Dot3Name, FAT_NAME_LEN, ' ');
|
||||||
|
for (TempName = FileName; *TempName; TempName++) {
|
||||||
|
if (*TempName == L'.') {
|
||||||
|
SeparateDot = TempName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SeparateDot == NULL) {
|
||||||
|
//
|
||||||
|
// Extended filename is not detected
|
||||||
|
//
|
||||||
|
MainNameLen = TempName - FileName;
|
||||||
|
ExtendName = TempName;
|
||||||
|
ExtendNameLen = 0;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Extended filename is detected
|
||||||
|
//
|
||||||
|
MainNameLen = SeparateDot - FileName;
|
||||||
|
ExtendName = SeparateDot + 1;
|
||||||
|
ExtendNameLen = TempName - ExtendName;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We scan the filename for the second time
|
||||||
|
// to check if there exists any extra blanks and dots
|
||||||
|
//
|
||||||
|
while (--TempName >= FileName) {
|
||||||
|
if ((*TempName == L'.' || *TempName == L' ') && (TempName != SeparateDot)) {
|
||||||
|
//
|
||||||
|
// There exist extra blanks and dots
|
||||||
|
//
|
||||||
|
PossibleShortName = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MainNameLen == 0) {
|
||||||
|
PossibleShortName = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MainNameLen > FAT_MAIN_NAME_LEN) {
|
||||||
|
PossibleShortName = FALSE;
|
||||||
|
MainNameLen = FAT_MAIN_NAME_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ExtendNameLen > FAT_EXTEND_NAME_LEN) {
|
||||||
|
PossibleShortName = FALSE;
|
||||||
|
ExtendNameLen = FAT_EXTEND_NAME_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FatStrToFat (FileName, MainNameLen, File8Dot3Name)) {
|
||||||
|
PossibleShortName = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FatStrToFat (ExtendName, ExtendNameLen, File8Dot3Name + FAT_MAIN_NAME_LEN)) {
|
||||||
|
PossibleShortName = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PossibleShortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
UINTN
|
||||||
|
FatTrimAsciiTrailingBlanks (
|
||||||
|
IN CHAR8 *Name,
|
||||||
|
IN UINTN Len
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Trim the trailing blanks of fat name.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Name - The Char8 string needs to be trimed.
|
||||||
|
Len - The length of the fat name.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The real length of the fat name after the trailing blanks are trimmed.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
while (Len > 0 && Name[Len - 1] == ' ') {
|
||||||
|
Len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Len;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatNameToStr (
|
||||||
|
IN CHAR8 *FatName,
|
||||||
|
IN UINTN Len,
|
||||||
|
IN UINTN LowerCase,
|
||||||
|
OUT CHAR16 *Str
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Convert the ascii fat name to the unicode string and strip trailing spaces,
|
||||||
|
and if necessary, convert the unicode string to lower case.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FatName - The Char8 string needs to be converted.
|
||||||
|
Len - The length of the fat name.
|
||||||
|
LowerCase - Indicate whether to convert the string to lower case.
|
||||||
|
Str - The result of the convertion.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// First, trim the trailing blanks
|
||||||
|
//
|
||||||
|
Len = FatTrimAsciiTrailingBlanks (FatName, Len);
|
||||||
|
//
|
||||||
|
// Convert fat string to unicode string
|
||||||
|
//
|
||||||
|
FatFatToStr (Len, FatName, Str);
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the name is to be lower cased, do it now
|
||||||
|
//
|
||||||
|
if (LowerCase != 0) {
|
||||||
|
FatStrLwr (Str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatCreate8Dot3Name (
|
||||||
|
IN FAT_OFILE *Parent,
|
||||||
|
IN FAT_DIRENT *DirEnt
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This function generates 8Dot3 name from user specified name for a newly created file.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Parent - The parent directory.
|
||||||
|
DirEnt - The directory entry whose 8Dot3Name needs to be generated.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
CHAR8 *ShortName;
|
||||||
|
CHAR8 *ShortNameChar;
|
||||||
|
UINTN BaseTagLen;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN Retry;
|
||||||
|
UINT8 Segment;
|
||||||
|
union {
|
||||||
|
UINT32 Crc;
|
||||||
|
struct HEX_DATA {
|
||||||
|
UINT8 Segment : HASH_VALUE_TAG_LEN;
|
||||||
|
} Hex[HASH_VALUE_TAG_LEN];
|
||||||
|
} HashValue;
|
||||||
|
//
|
||||||
|
// Make sure the whole directory has been loaded
|
||||||
|
//
|
||||||
|
ASSERT (Parent->ODir->EndOfDir);
|
||||||
|
ShortName = DirEnt->Entry.FileName;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Trim trailing blanks of 8.3 name
|
||||||
|
//
|
||||||
|
BaseTagLen = FatTrimAsciiTrailingBlanks (ShortName, FAT_MAIN_NAME_LEN);
|
||||||
|
if (BaseTagLen > SPEC_BASE_TAG_LEN) {
|
||||||
|
BaseTagLen = SPEC_BASE_TAG_LEN;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We first use the algorithm described by spec.
|
||||||
|
//
|
||||||
|
ShortNameChar = ShortName + BaseTagLen;
|
||||||
|
*ShortNameChar++ = '~';
|
||||||
|
*ShortNameChar = '1';
|
||||||
|
Retry = 0;
|
||||||
|
while (*FatShortNameHashSearch (Parent->ODir, ShortName) != NULL) {
|
||||||
|
*ShortNameChar = (CHAR8)(*ShortNameChar + 1);
|
||||||
|
if (++Retry == MAX_SPEC_RETRY) {
|
||||||
|
//
|
||||||
|
// We use new algorithm to generate 8.3 name
|
||||||
|
//
|
||||||
|
ASSERT (DirEnt->FileString != NULL);
|
||||||
|
gBS->CalculateCrc32 (DirEnt->FileString, StrSize (DirEnt->FileString), &HashValue.Crc);
|
||||||
|
|
||||||
|
if (BaseTagLen > HASH_BASE_TAG_LEN) {
|
||||||
|
BaseTagLen = HASH_BASE_TAG_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShortNameChar = ShortName + BaseTagLen;
|
||||||
|
for (Index = 0; Index < HASH_VALUE_TAG_LEN; Index++) {
|
||||||
|
Segment = HashValue.Hex[Index].Segment;
|
||||||
|
if (Segment > 9) {
|
||||||
|
*ShortNameChar++ = (CHAR8)(Segment - 10 + 'A');
|
||||||
|
} else {
|
||||||
|
*ShortNameChar++ = (CHAR8)(Segment + '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*ShortNameChar++ = '~';
|
||||||
|
*ShortNameChar = '1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
UINT8
|
||||||
|
FatCheckNameCase (
|
||||||
|
IN CHAR16 *Str,
|
||||||
|
IN UINT8 InCaseFlag
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Check the string is lower case or upper case
|
||||||
|
and it is used by fatname to dir entry count
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Str - The string which needs to be checked.
|
||||||
|
InCaseFlag - The input case flag which is returned when the string is lower case.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
OutCaseFlag - The output case flag.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
CHAR16 Buffer[FAT_MAIN_NAME_LEN + 1];
|
||||||
|
UINT8 OutCaseFlag;
|
||||||
|
|
||||||
|
ASSERT (StrSize (Str) <= sizeof (Buffer));
|
||||||
|
//
|
||||||
|
// Assume the case of input string is mixed
|
||||||
|
//
|
||||||
|
OutCaseFlag = FAT_CASE_MIXED;
|
||||||
|
//
|
||||||
|
// Lower case a copy of the string, if it matches the
|
||||||
|
// original then the string is lower case
|
||||||
|
//
|
||||||
|
StrCpy (Buffer, Str);
|
||||||
|
FatStrLwr (Buffer);
|
||||||
|
if (StrCmp (Str, Buffer) == 0) {
|
||||||
|
OutCaseFlag = InCaseFlag;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Upper case a copy of the string, if it matches the
|
||||||
|
// original then the string is upper case
|
||||||
|
//
|
||||||
|
StrCpy (Buffer, Str);
|
||||||
|
FatStrUpr (Buffer);
|
||||||
|
if (StrCmp (Str, Buffer) == 0) {
|
||||||
|
OutCaseFlag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OutCaseFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatSetCaseFlag (
|
||||||
|
IN FAT_DIRENT *DirEnt
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the caseflag value for the directory entry.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DirEnt - The logical directory entry whose caseflag value is to be set.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
CHAR16 LfnBuffer[FAT_MAIN_NAME_LEN + 1 + FAT_EXTEND_NAME_LEN + 1];
|
||||||
|
CHAR16 *TempCharPtr;
|
||||||
|
CHAR16 *ExtendName;
|
||||||
|
CHAR16 *FileNameCharPtr;
|
||||||
|
UINT8 CaseFlag;
|
||||||
|
|
||||||
|
ExtendName = NULL;
|
||||||
|
TempCharPtr = LfnBuffer;
|
||||||
|
FileNameCharPtr = DirEnt->FileString;
|
||||||
|
ASSERT (StrSize (DirEnt->FileString) <= sizeof (LfnBuffer));
|
||||||
|
while ((*TempCharPtr = *FileNameCharPtr) != 0) {
|
||||||
|
if (*TempCharPtr == L'.') {
|
||||||
|
ExtendName = TempCharPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempCharPtr++;
|
||||||
|
FileNameCharPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
CaseFlag = 0;
|
||||||
|
if (ExtendName != NULL) {
|
||||||
|
*ExtendName = 0;
|
||||||
|
ExtendName++;
|
||||||
|
CaseFlag = (UINT8)(CaseFlag | FatCheckNameCase (ExtendName, FAT_CASE_EXT_LOWER));
|
||||||
|
}
|
||||||
|
|
||||||
|
CaseFlag = (UINT8)(CaseFlag | FatCheckNameCase (LfnBuffer, FAT_CASE_NAME_LOWER));
|
||||||
|
if ((CaseFlag & FAT_CASE_MIXED) == 0) {
|
||||||
|
//
|
||||||
|
// We just need one directory entry to store this file name entry
|
||||||
|
//
|
||||||
|
DirEnt->Entry.CaseFlag = CaseFlag;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// We need one extra directory entry to store the mixed case entry
|
||||||
|
//
|
||||||
|
DirEnt->Entry.CaseFlag = 0;
|
||||||
|
DirEnt->EntryCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatGetFileNameViaCaseFlag (
|
||||||
|
IN FAT_DIRENT *DirEnt,
|
||||||
|
OUT CHAR16 *FileString
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Convert the 8.3 ASCII fat name to cased Unicode string according to case flag.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DirEnt - The corresponding directory entry.
|
||||||
|
FileString - The output Unicode file name.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINT8 CaseFlag;
|
||||||
|
CHAR8 *File8Dot3Name;
|
||||||
|
CHAR16 TempExt[1 + FAT_EXTEND_NAME_LEN + 1];
|
||||||
|
//
|
||||||
|
// Store file extension like ".txt"
|
||||||
|
//
|
||||||
|
CaseFlag = DirEnt->Entry.CaseFlag;
|
||||||
|
File8Dot3Name = DirEnt->Entry.FileName;
|
||||||
|
|
||||||
|
FatNameToStr (File8Dot3Name, FAT_MAIN_NAME_LEN, CaseFlag & FAT_CASE_NAME_LOWER, FileString);
|
||||||
|
FatNameToStr (File8Dot3Name + FAT_MAIN_NAME_LEN, FAT_EXTEND_NAME_LEN, CaseFlag & FAT_CASE_EXT_LOWER, &TempExt[1]);
|
||||||
|
if (TempExt[1] != 0) {
|
||||||
|
TempExt[0] = L'.';
|
||||||
|
StrCat (FileString, TempExt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8
|
||||||
|
FatCheckSum (
|
||||||
|
IN CHAR8 *ShortNameString
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the Check sum for a short name.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ShortNameString - The short name for a file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
Sum - UINT8 checksum.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN ShortNameLen;
|
||||||
|
UINT8 Sum;
|
||||||
|
Sum = 0;
|
||||||
|
for (ShortNameLen = FAT_NAME_LEN; ShortNameLen != 0; ShortNameLen--) {
|
||||||
|
Sum = (UINT8)(((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *ShortNameString++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHAR16 *
|
||||||
|
FatGetNextNameComponent (
|
||||||
|
IN CHAR16 *Path,
|
||||||
|
OUT CHAR16 *Name
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Takes Path as input, returns the next name component
|
||||||
|
in Name, and returns the position after Name (e.g., the
|
||||||
|
start of the next name component)
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Path - The path of one file.
|
||||||
|
Name - The next name component in Path.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The position after Name in the Path
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
while (*Path != 0 && *Path != PATH_NAME_SEPARATOR) {
|
||||||
|
*Name++ = *Path++;
|
||||||
|
}
|
||||||
|
*Name = 0;
|
||||||
|
//
|
||||||
|
// Get off of trailing path name separator
|
||||||
|
//
|
||||||
|
while (*Path == PATH_NAME_SEPARATOR) {
|
||||||
|
Path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
FatFileNameIsValid (
|
||||||
|
IN CHAR16 *InputFileName,
|
||||||
|
OUT CHAR16 *OutputFileName
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Check whether the IFileName is valid long file name. If the IFileName is a valid
|
||||||
|
long file name, then we trim the possible leading blanks and leading/trailing dots.
|
||||||
|
the trimmed filename is stored in OutputFileName
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
InputFileName - The input file name.
|
||||||
|
OutputFileName - The output file name.
|
||||||
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
TRUE - The InputFileName is a valid long file name.
|
||||||
|
FALSE - The InputFileName is not a valid long file name.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
CHAR16 *TempNamePointer;
|
||||||
|
CHAR16 TempChar;
|
||||||
|
//
|
||||||
|
// Trim Leading blanks
|
||||||
|
//
|
||||||
|
while (*InputFileName == L' ') {
|
||||||
|
InputFileName++;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempNamePointer = OutputFileName;
|
||||||
|
while (*InputFileName != 0) {
|
||||||
|
*TempNamePointer++ = *InputFileName++;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Trim Trailing blanks and dots
|
||||||
|
//
|
||||||
|
while (TempNamePointer > OutputFileName) {
|
||||||
|
TempChar = *(TempNamePointer - 1);
|
||||||
|
if (TempChar != L' ' && TempChar != L'.') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TempNamePointer--;
|
||||||
|
}
|
||||||
|
|
||||||
|
*TempNamePointer = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Per FAT Spec the file name should meet the following criteria:
|
||||||
|
// C1. Length (FileLongName) <= 255
|
||||||
|
// C2. Length (X:FileFullPath<NUL>) <= 260
|
||||||
|
// Here we check C1.
|
||||||
|
//
|
||||||
|
if (TempNamePointer - OutputFileName > EFI_FILE_STRING_LENGTH) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// See if there is any illegal characters within the name
|
||||||
|
//
|
||||||
|
do {
|
||||||
|
if (*OutputFileName < 0x20 ||
|
||||||
|
*OutputFileName == '\"' ||
|
||||||
|
*OutputFileName == '*' ||
|
||||||
|
*OutputFileName == '/' ||
|
||||||
|
*OutputFileName == ':' ||
|
||||||
|
*OutputFileName == '<' ||
|
||||||
|
*OutputFileName == '>' ||
|
||||||
|
*OutputFileName == '?' ||
|
||||||
|
*OutputFileName == '\\' ||
|
||||||
|
*OutputFileName == '|'
|
||||||
|
) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputFileName++;
|
||||||
|
} while (*OutputFileName != 0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
816
FatPkg/EnhancedFatDxe/FileSpace.c
Normal file
816
FatPkg/EnhancedFatDxe/FileSpace.c
Normal file
@ -0,0 +1,816 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
FileSpace.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Routines dealing with disk spaces and FAT table entries
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
VOID *
|
||||||
|
FatLoadFatEntry (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN Index
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the FAT entry of the volume, which is identified with the Index.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
Index - The index of the FAT entry of the volume.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The buffer of the FAT entry
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN Pos;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
if (Index > (Volume->MaxCluster + 1)) {
|
||||||
|
Volume->FatEntryBuffer = (UINT32) -1;
|
||||||
|
return &Volume->FatEntryBuffer;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Compute buffer position needed
|
||||||
|
//
|
||||||
|
switch (Volume->FatType) {
|
||||||
|
case FAT12:
|
||||||
|
Pos = FAT_POS_FAT12 (Index);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT16:
|
||||||
|
Pos = FAT_POS_FAT16 (Index);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Pos = FAT_POS_FAT32 (Index);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Set the position and read the buffer
|
||||||
|
//
|
||||||
|
Volume->FatEntryPos = Volume->FatPos + Pos;
|
||||||
|
Status = FatDiskIo (
|
||||||
|
Volume,
|
||||||
|
READ_FAT,
|
||||||
|
Volume->FatEntryPos,
|
||||||
|
Volume->FatEntrySize,
|
||||||
|
&Volume->FatEntryBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Volume->FatEntryBuffer = (UINT32) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Volume->FatEntryBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
UINTN
|
||||||
|
FatGetFatEntry (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN Index
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the FAT entry value of the volume, which is identified with the Index.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
Index - The index of the FAT entry of the volume.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The value of the FAT entry.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
VOID *Pos;
|
||||||
|
UINT8 *E12;
|
||||||
|
UINT16 *E16;
|
||||||
|
UINT32 *E32;
|
||||||
|
UINTN Accum;
|
||||||
|
|
||||||
|
Pos = FatLoadFatEntry (Volume, Index);
|
||||||
|
|
||||||
|
if (Index > (Volume->MaxCluster + 1)) {
|
||||||
|
return (UINTN) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Volume->FatType) {
|
||||||
|
case FAT12:
|
||||||
|
E12 = Pos;
|
||||||
|
Accum = E12[0] | (E12[1] << 8);
|
||||||
|
Accum = FAT_ODD_CLUSTER_FAT12 (Index) ? (Accum >> 4) : (Accum & FAT_CLUSTER_MASK_FAT12);
|
||||||
|
Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT12) ? FAT_CLUSTER_SPECIAL_EXT : 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT16:
|
||||||
|
E16 = Pos;
|
||||||
|
Accum = *E16;
|
||||||
|
Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT16) ? FAT_CLUSTER_SPECIAL_EXT : 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
E32 = Pos;
|
||||||
|
Accum = *E32 & FAT_CLUSTER_MASK_FAT32;
|
||||||
|
Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT32) ? FAT_CLUSTER_SPECIAL_EXT : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Accum;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetFatEntry (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN Index,
|
||||||
|
IN UINTN Value
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the FAT entry value of the volume, which is identified with the Index.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
Index - The index of the FAT entry of the volume.
|
||||||
|
Value - The new value of the FAT entry.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the new FAT entry value sucessfully.
|
||||||
|
EFI_VOLUME_CORRUPTED - The FAT type of the volume is error.
|
||||||
|
other - An error occurred when operation the FAT entries.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
VOID *Pos;
|
||||||
|
UINT8 *E12;
|
||||||
|
UINT16 *E16;
|
||||||
|
UINT32 *E32;
|
||||||
|
UINTN Accum;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN OriginalVal;
|
||||||
|
|
||||||
|
if (Index < FAT_MIN_CLUSTER) {
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
OriginalVal = FatGetFatEntry (Volume, Index);
|
||||||
|
if (Value == FAT_CLUSTER_FREE && OriginalVal != FAT_CLUSTER_FREE) {
|
||||||
|
Volume->FatInfoSector.FreeInfo.ClusterCount += 1;
|
||||||
|
if (Index < Volume->FatInfoSector.FreeInfo.NextCluster) {
|
||||||
|
Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;
|
||||||
|
}
|
||||||
|
} else if (Value != FAT_CLUSTER_FREE && OriginalVal == FAT_CLUSTER_FREE) {
|
||||||
|
if (Volume->FatInfoSector.FreeInfo.ClusterCount != 0) {
|
||||||
|
Volume->FatInfoSector.FreeInfo.ClusterCount -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Make sure the entry is in memory
|
||||||
|
//
|
||||||
|
Pos = FatLoadFatEntry (Volume, Index);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update the value
|
||||||
|
//
|
||||||
|
switch (Volume->FatType) {
|
||||||
|
case FAT12:
|
||||||
|
E12 = Pos;
|
||||||
|
Accum = E12[0] | (E12[1] << 8);
|
||||||
|
Value = Value & FAT_CLUSTER_MASK_FAT12;
|
||||||
|
|
||||||
|
if (FAT_ODD_CLUSTER_FAT12 (Index)) {
|
||||||
|
Accum = (Value << 4) | (Accum & 0xF);
|
||||||
|
} else {
|
||||||
|
Accum = Value | (Accum & FAT_CLUSTER_UNMASK_FAT12);
|
||||||
|
}
|
||||||
|
|
||||||
|
E12[0] = (UINT8) (Accum & 0xFF);
|
||||||
|
E12[1] = (UINT8) (Accum >> 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FAT16:
|
||||||
|
E16 = Pos;
|
||||||
|
*E16 = (UINT16) Value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
E32 = Pos;
|
||||||
|
*E32 = (*E32 & FAT_CLUSTER_UNMASK_FAT32) | (UINT32) (Value & FAT_CLUSTER_MASK_FAT32);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the volume's dirty bit is not set, set it now
|
||||||
|
//
|
||||||
|
if (!Volume->FatDirty && Volume->FatType != FAT12) {
|
||||||
|
Volume->FatDirty = TRUE;
|
||||||
|
FatAccessVolumeDirty (Volume, WRITE_FAT, &Volume->DirtyValue);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Write the updated fat entry value to the volume
|
||||||
|
// The fat is the first fat, and other fat will be in sync
|
||||||
|
// when the FAT cache flush back.
|
||||||
|
//
|
||||||
|
Status = FatDiskIo (
|
||||||
|
Volume,
|
||||||
|
WRITE_FAT,
|
||||||
|
Volume->FatEntryPos,
|
||||||
|
Volume->FatEntrySize,
|
||||||
|
&Volume->FatEntryBuffer
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
FatFreeClusters (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN Cluster
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Free the cluster clain.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
Cluster - The first cluster of cluster chain.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The cluster chain is freed successfully.
|
||||||
|
EFI_VOLUME_CORRUPTED - There are errors in the file's clusters.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN LastCluster;
|
||||||
|
|
||||||
|
while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
|
||||||
|
if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatShrinkEof: cluster chain corrupt\n"));
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastCluster = Cluster;
|
||||||
|
Cluster = FatGetFatEntry (Volume, Cluster);
|
||||||
|
FatSetFatEntry (Volume, LastCluster, FAT_CLUSTER_FREE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
UINTN
|
||||||
|
FatAllocateCluster (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Allocate a free cluster and return the cluster index.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The index of the free cluster
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN Cluster;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Start looking at FatFreePos for the next unallocated cluster
|
||||||
|
//
|
||||||
|
if (Volume->DiskError) {
|
||||||
|
return (UINTN) FAT_CLUSTER_LAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
//
|
||||||
|
// If the end of the list, return no available cluster
|
||||||
|
//
|
||||||
|
if (Volume->FatInfoSector.FreeInfo.NextCluster > (Volume->MaxCluster + 1)) {
|
||||||
|
if (Volume->FreeInfoValid && 0 < (INT32) (Volume->FatInfoSector.FreeInfo.ClusterCount)) {
|
||||||
|
Volume->FreeInfoValid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatComputeFreeInfo (Volume);
|
||||||
|
if (Volume->FatInfoSector.FreeInfo.NextCluster > (Volume->MaxCluster + 1)) {
|
||||||
|
return (UINTN) FAT_CLUSTER_LAST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cluster = FatGetFatEntry (Volume, Volume->FatInfoSector.FreeInfo.NextCluster);
|
||||||
|
if (Cluster == FAT_CLUSTER_FREE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Try the next cluster
|
||||||
|
//
|
||||||
|
Volume->FatInfoSector.FreeInfo.NextCluster += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cluster = Volume->FatInfoSector.FreeInfo.NextCluster;
|
||||||
|
Volume->FatInfoSector.FreeInfo.NextCluster += 1;
|
||||||
|
return Cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
UINTN
|
||||||
|
FatSizeToClusters (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN Size
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Count the number of clusters given a size
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - The file system volume.
|
||||||
|
Size - The size in bytes.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The number of the clusters.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN Clusters;
|
||||||
|
|
||||||
|
Clusters = Size >> Volume->ClusterAlignment;
|
||||||
|
if ((Size & (Volume->ClusterSize - 1)) > 0) {
|
||||||
|
Clusters += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Clusters;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatShrinkEof (
|
||||||
|
IN FAT_OFILE *OFile
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Shrink the end of the open file base on the file size.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Shrinked sucessfully.
|
||||||
|
EFI_VOLUME_CORRUPTED - There are errors in the file's clusters.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
UINTN NewSize;
|
||||||
|
UINTN CurSize;
|
||||||
|
UINTN Cluster;
|
||||||
|
UINTN LastCluster;
|
||||||
|
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
ASSERT_VOLUME_LOCKED (Volume);
|
||||||
|
|
||||||
|
NewSize = FatSizeToClusters (Volume, OFile->FileSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find the address of the last cluster
|
||||||
|
//
|
||||||
|
Cluster = OFile->FileCluster;
|
||||||
|
LastCluster = FAT_CLUSTER_FREE;
|
||||||
|
|
||||||
|
if (NewSize != 0) {
|
||||||
|
|
||||||
|
for (CurSize = 0; CurSize < NewSize; CurSize++) {
|
||||||
|
if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatShrinkEof: cluster chain corrupt\n"));
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastCluster = Cluster;
|
||||||
|
Cluster = FatGetFatEntry (Volume, Cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Check to see if the file is already completely truncated
|
||||||
|
//
|
||||||
|
if (Cluster == FAT_CLUSTER_FREE) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// The file is being completely truncated.
|
||||||
|
//
|
||||||
|
OFile->FileCluster = FAT_CLUSTER_FREE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Set CurrentCluster == FileCluster
|
||||||
|
// to force a recalculation of Position related stuffs
|
||||||
|
//
|
||||||
|
OFile->FileCurrentCluster = OFile->FileCluster;
|
||||||
|
OFile->FileLastCluster = LastCluster;
|
||||||
|
OFile->Dirty = TRUE;
|
||||||
|
//
|
||||||
|
// Free the remaining cluster chain
|
||||||
|
//
|
||||||
|
return FatFreeClusters (Volume, Cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatGrowEof (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN UINT64 NewSizeInBytes
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Grow the end of the open file base on the NewSizeInBytes.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file.
|
||||||
|
NewSizeInBytes - The new size in bytes of the open file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The file is grown sucessfully.
|
||||||
|
EFI_UNSUPPORTED - The file size is larger than 4GB.
|
||||||
|
EFI_VOLUME_CORRUPTED - There are errors in the files' clusters.
|
||||||
|
EFI_VOLUME_FULL - The volume is full and can not grow the file.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Cluster;
|
||||||
|
UINTN CurSize;
|
||||||
|
UINTN NewSize;
|
||||||
|
UINTN LastCluster;
|
||||||
|
UINTN NewCluster;
|
||||||
|
UINTN ClusterCount;
|
||||||
|
|
||||||
|
//
|
||||||
|
// For FAT file system, the max file is 4GB.
|
||||||
|
//
|
||||||
|
if (NewSizeInBytes > 0x0FFFFFFFFL) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
ASSERT_VOLUME_LOCKED (Volume);
|
||||||
|
//
|
||||||
|
// If the file is already large enough, do nothing
|
||||||
|
//
|
||||||
|
CurSize = FatSizeToClusters (Volume, OFile->FileSize);
|
||||||
|
NewSize = FatSizeToClusters (Volume, (UINTN) NewSizeInBytes);
|
||||||
|
|
||||||
|
if (CurSize < NewSize) {
|
||||||
|
//
|
||||||
|
// If we haven't found the files last cluster do it now
|
||||||
|
//
|
||||||
|
if ((OFile->FileCluster != 0) && (OFile->FileLastCluster == 0)) {
|
||||||
|
Cluster = OFile->FileCluster;
|
||||||
|
ClusterCount = 0;
|
||||||
|
|
||||||
|
while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
|
||||||
|
if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
|
||||||
|
|
||||||
|
DEBUG (
|
||||||
|
(EFI_D_INIT | EFI_D_ERROR,
|
||||||
|
"FatGrowEof: cluster chain corrupt\n")
|
||||||
|
);
|
||||||
|
Status = EFI_VOLUME_CORRUPTED;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterCount++;
|
||||||
|
OFile->FileLastCluster = Cluster;
|
||||||
|
Cluster = FatGetFatEntry (Volume, Cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClusterCount != CurSize) {
|
||||||
|
DEBUG (
|
||||||
|
(EFI_D_INIT | EFI_D_ERROR,
|
||||||
|
"FatGrowEof: cluster chain size does not match file size\n")
|
||||||
|
);
|
||||||
|
Status = EFI_VOLUME_CORRUPTED;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Loop until we've allocated enough space
|
||||||
|
//
|
||||||
|
LastCluster = OFile->FileLastCluster;
|
||||||
|
|
||||||
|
while (CurSize < NewSize) {
|
||||||
|
NewCluster = FatAllocateCluster (Volume);
|
||||||
|
if (FAT_END_OF_FAT_CHAIN (NewCluster)) {
|
||||||
|
if (LastCluster != FAT_CLUSTER_FREE) {
|
||||||
|
FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
|
||||||
|
OFile->FileLastCluster = LastCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EFI_VOLUME_FULL;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LastCluster != 0) {
|
||||||
|
FatSetFatEntry (Volume, LastCluster, NewCluster);
|
||||||
|
} else {
|
||||||
|
OFile->FileCluster = NewCluster;
|
||||||
|
OFile->FileCurrentCluster = NewCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastCluster = NewCluster;
|
||||||
|
CurSize += 1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Terminate the cluster list
|
||||||
|
//
|
||||||
|
FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
|
||||||
|
OFile->FileLastCluster = LastCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile->FileSize = (UINTN) NewSizeInBytes;
|
||||||
|
OFile->Dirty = TRUE;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
Done:
|
||||||
|
FatShrinkEof (OFile);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatOFilePosition (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN UINTN Position,
|
||||||
|
IN UINTN PosLimit
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Seek OFile to requested position, and calculate the number of
|
||||||
|
consecutive clusters from the position in the file
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file.
|
||||||
|
Position - The file's position which will be accessed.
|
||||||
|
PosLimit - The maximum length current reading/writing may access
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the info successfully.
|
||||||
|
EFI_VOLUME_CORRUPTED - Cluster chain corrupt.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
UINTN ClusterSize;
|
||||||
|
UINTN Cluster;
|
||||||
|
UINTN StartPos;
|
||||||
|
UINTN Run;
|
||||||
|
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
ClusterSize = Volume->ClusterSize;
|
||||||
|
|
||||||
|
ASSERT_VOLUME_LOCKED (Volume);
|
||||||
|
|
||||||
|
//
|
||||||
|
// If this is the fixed root dir, then compute it's position
|
||||||
|
// from it's fixed info in the fat bpb
|
||||||
|
//
|
||||||
|
if (OFile->IsFixedRootDir) {
|
||||||
|
OFile->PosDisk = Volume->RootPos + Position;
|
||||||
|
Run = OFile->FileSize - Position;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Run the file's cluster chain to find the current position
|
||||||
|
// If possible, run from the current cluster rather than
|
||||||
|
// start from beginning
|
||||||
|
// Assumption: OFile->Position is always consistent with
|
||||||
|
// OFile->FileCurrentCluster.
|
||||||
|
// OFile->Position is not modified outside this function;
|
||||||
|
// OFile->FileCurrentCluster is modified outside this function
|
||||||
|
// to be the same as OFile->FileCluster
|
||||||
|
// when OFile->FileCluster is updated, so make a check of this
|
||||||
|
// and invalidate the original OFile->Position in this case
|
||||||
|
//
|
||||||
|
Cluster = OFile->FileCurrentCluster;
|
||||||
|
StartPos = OFile->Position;
|
||||||
|
if (Position < StartPos || OFile->FileCluster == Cluster) {
|
||||||
|
StartPos = 0;
|
||||||
|
Cluster = OFile->FileCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (StartPos + ClusterSize <= Position) {
|
||||||
|
StartPos += ClusterSize;
|
||||||
|
if (Cluster == FAT_CLUSTER_FREE || (Cluster >= FAT_CLUSTER_SPECIAL)) {
|
||||||
|
DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatOFilePosition:"" cluster chain corrupt\n"));
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cluster = FatGetFatEntry (Volume, Cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cluster < FAT_MIN_CLUSTER) {
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile->PosDisk = Volume->FirstClusterPos +
|
||||||
|
LShiftU64 (Cluster - FAT_MIN_CLUSTER, Volume->ClusterAlignment) +
|
||||||
|
Position - StartPos;
|
||||||
|
OFile->FileCurrentCluster = Cluster;
|
||||||
|
OFile->Position = StartPos;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Compute the number of consecutive clusters in the file
|
||||||
|
//
|
||||||
|
Run = StartPos + ClusterSize - Position;
|
||||||
|
if (!FAT_END_OF_FAT_CHAIN (Cluster)) {
|
||||||
|
while ((FatGetFatEntry (Volume, Cluster) == Cluster + 1) && Run < PosLimit) {
|
||||||
|
Run += ClusterSize;
|
||||||
|
Cluster += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile->PosRem = Run;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINTN
|
||||||
|
FatPhysicalDirSize (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN Cluster
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the size of directory of the open file
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - The File System Volume.
|
||||||
|
Cluster - The Starting cluster.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The physical size of the file starting at the input cluster, if there is error in the
|
||||||
|
cluster chain, the return value is 0.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN Size;
|
||||||
|
ASSERT_VOLUME_LOCKED (Volume);
|
||||||
|
//
|
||||||
|
// Run the cluster chain for the OFile
|
||||||
|
//
|
||||||
|
Size = 0;
|
||||||
|
//
|
||||||
|
// N.B. ".." directories on some media do not contain a starting
|
||||||
|
// cluster. In the case of "." or ".." we don't need the size anyway.
|
||||||
|
//
|
||||||
|
if (Cluster != 0) {
|
||||||
|
while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
|
||||||
|
if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
|
||||||
|
DEBUG (
|
||||||
|
(EFI_D_INIT | EFI_D_ERROR,
|
||||||
|
"FATDirSize: cluster chain corrupt\n")
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size += Volume->ClusterSize;
|
||||||
|
Cluster = FatGetFatEntry (Volume, Cluster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
FatPhysicalFileSize (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN RealSize
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the physical size of a file on the disk.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - The file system volume.
|
||||||
|
RealSize - The real size of a file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The physical size of a file on the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN ClusterSizeMask;
|
||||||
|
UINT64 PhysicalSize;
|
||||||
|
ClusterSizeMask = Volume->ClusterSize - 1;
|
||||||
|
PhysicalSize = (RealSize + ClusterSizeMask) & (~((UINT64) ClusterSizeMask));
|
||||||
|
return PhysicalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatComputeFreeInfo (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Update the free cluster info of FatInfoSector of the volume.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If we don't have valid info, compute it now
|
||||||
|
//
|
||||||
|
if (!Volume->FreeInfoValid) {
|
||||||
|
|
||||||
|
Volume->FreeInfoValid = TRUE;
|
||||||
|
Volume->FatInfoSector.FreeInfo.ClusterCount = 0;
|
||||||
|
for (Index = Volume->MaxCluster + 1; Index >= FAT_MIN_CLUSTER; Index--) {
|
||||||
|
if (Volume->DiskError) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FatGetFatEntry (Volume, Index) == FAT_CLUSTER_FREE) {
|
||||||
|
Volume->FatInfoSector.FreeInfo.ClusterCount += 1;
|
||||||
|
Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Volume->FatInfoSector.Signature = FAT_INFO_SIGNATURE;
|
||||||
|
Volume->FatInfoSector.InfoBeginSignature = FAT_INFO_BEGIN_SIGNATURE;
|
||||||
|
Volume->FatInfoSector.InfoEndSignature = FAT_INFO_END_SIGNATURE;
|
||||||
|
}
|
||||||
|
}
|
480
FatPkg/EnhancedFatDxe/Flush.c
Normal file
480
FatPkg/EnhancedFatDxe/Flush.c
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
flush.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Routines that check references and flush OFiles
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatFlush (
|
||||||
|
IN EFI_FILE *FHand
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Flushes all data associated with the file handle.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - Handle to file to flush.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Flushed the file successfully.
|
||||||
|
EFI_WRITE_PROTECTED - The volume is read only.
|
||||||
|
EFI_ACCESS_DENIED - The file is read only.
|
||||||
|
Others - Flushing of the file failed.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
IFile = IFILE_FROM_FHAND (FHand);
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the file has a permanent error, return it
|
||||||
|
//
|
||||||
|
if (EFI_ERROR (OFile->Error)) {
|
||||||
|
return OFile->Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Volume->ReadOnly) {
|
||||||
|
return EFI_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If read only, return error
|
||||||
|
//
|
||||||
|
if (IFile->ReadOnly) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Flush the OFile
|
||||||
|
//
|
||||||
|
FatAcquireLock ();
|
||||||
|
Status = FatOFileFlush (OFile);
|
||||||
|
Status = FatCleanupVolume (OFile->Volume, OFile, Status);
|
||||||
|
FatReleaseLock ();
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatClose (
|
||||||
|
IN EFI_FILE *FHand
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Flushes & Closes the file handle.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - Handle to the file to delete.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Closed the file successfully.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
|
||||||
|
IFile = IFILE_FROM_FHAND (FHand);
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lock the volume
|
||||||
|
//
|
||||||
|
FatAcquireLock ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Close the file instance handle
|
||||||
|
//
|
||||||
|
FatIFileClose (IFile);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Done. Unlock the volume
|
||||||
|
//
|
||||||
|
FatCleanupVolume (Volume, OFile, EFI_SUCCESS);
|
||||||
|
FatReleaseLock ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Close always succeed
|
||||||
|
//
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatIFileClose (
|
||||||
|
FAT_IFILE *IFile
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Close the open file instance.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
IFile - Open file instance.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Closed the file successfully.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
|
||||||
|
ASSERT_VOLUME_LOCKED (Volume);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Remove the IFile struct
|
||||||
|
//
|
||||||
|
RemoveEntryList (&IFile->Link);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add the OFile to the check reference list
|
||||||
|
//
|
||||||
|
if (OFile->CheckLink.ForwardLink == NULL) {
|
||||||
|
InsertHeadList (&Volume->CheckRef, &OFile->CheckLink);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Done. Free the open instance structure
|
||||||
|
//
|
||||||
|
FreePool (IFile);
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatOFileFlush (
|
||||||
|
IN FAT_OFILE *OFile
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Flush the data associated with an open file.
|
||||||
|
In this implementation, only last Mod/Access time is updated.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The OFile is flushed successfully.
|
||||||
|
Others - An error occurred when flushing this OFile.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FAT_OFILE *Parent;
|
||||||
|
FAT_DIRENT *DirEnt;
|
||||||
|
FAT_DATE_TIME FatNow;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Flush each entry up the tree while dirty
|
||||||
|
//
|
||||||
|
do {
|
||||||
|
//
|
||||||
|
// If the file has a permanant error, then don't write any
|
||||||
|
// of its data to the device (may be from different media)
|
||||||
|
//
|
||||||
|
if (EFI_ERROR (OFile->Error)) {
|
||||||
|
return OFile->Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
Parent = OFile->Parent;
|
||||||
|
DirEnt = OFile->DirEnt;
|
||||||
|
if (OFile->Dirty) {
|
||||||
|
//
|
||||||
|
// Update the last modification time
|
||||||
|
//
|
||||||
|
FatGetCurrentFatTime (&FatNow);
|
||||||
|
CopyMem (&DirEnt->Entry.FileLastAccess, &FatNow.Date, sizeof (FAT_DATE));
|
||||||
|
if (!OFile->PreserveLastModification) {
|
||||||
|
FatGetCurrentFatTime (&DirEnt->Entry.FileModificationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile->PreserveLastModification = FALSE;
|
||||||
|
if (OFile->Archive) {
|
||||||
|
DirEnt->Entry.Attributes |= FAT_ATTRIBUTE_ARCHIVE;
|
||||||
|
OFile->Archive = FALSE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Write the directory entry
|
||||||
|
//
|
||||||
|
if (Parent != NULL && !DirEnt->Invalid) {
|
||||||
|
//
|
||||||
|
// Write the OFile's directory entry
|
||||||
|
//
|
||||||
|
Status = FatStoreDirEnt (Parent, DirEnt);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile->Dirty = FALSE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Check the parent
|
||||||
|
//
|
||||||
|
OFile = Parent;
|
||||||
|
} while (OFile != NULL);
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
FatCheckOFileRef (
|
||||||
|
IN FAT_OFILE *OFile
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Check the references of the OFile.
|
||||||
|
If the OFile (that is checked) is no longer
|
||||||
|
referenced, then it is freed.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The OFile to be checked.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
TRUE - The OFile is not referenced and freed.
|
||||||
|
FALSE - The OFile is kept.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// If the OFile is on the check ref list, remove it
|
||||||
|
//
|
||||||
|
if (OFile->CheckLink.ForwardLink != NULL) {
|
||||||
|
RemoveEntryList (&OFile->CheckLink);
|
||||||
|
OFile->CheckLink.ForwardLink = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatOFileFlush (OFile);
|
||||||
|
//
|
||||||
|
// Are there any references to this OFile?
|
||||||
|
//
|
||||||
|
if (!IsListEmpty (&OFile->Opens) || !IsListEmpty (&OFile->ChildHead)) {
|
||||||
|
//
|
||||||
|
// The OFile cannot be freed
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Free the Ofile
|
||||||
|
//
|
||||||
|
FatCloseDirEnt (OFile->DirEnt);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
FatCheckVolumeRef (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Check the references of all open files on the volume.
|
||||||
|
Any open file (that is checked) that is no longer
|
||||||
|
referenced, is freed - and it's parent open file
|
||||||
|
is then referenced checked.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - The volume to check the pending open file list.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
FAT_OFILE *Parent;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check all files on the pending check list
|
||||||
|
//
|
||||||
|
while (!IsListEmpty (&Volume->CheckRef)) {
|
||||||
|
//
|
||||||
|
// Start with the first file listed
|
||||||
|
//
|
||||||
|
Parent = OFILE_FROM_CHECKLINK (Volume->CheckRef.ForwardLink);
|
||||||
|
//
|
||||||
|
// Go up the tree cleaning up any un-referenced OFiles
|
||||||
|
//
|
||||||
|
while (Parent != NULL) {
|
||||||
|
OFile = Parent;
|
||||||
|
Parent = OFile->Parent;
|
||||||
|
if (!FatCheckOFileRef (OFile)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatCleanupVolume (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN EFI_STATUS EfiStatus
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set error status for a specific OFile, reference checking the volume.
|
||||||
|
If volume is already marked as invalid, and all resources are freed
|
||||||
|
after reference checking, the file system protocol is uninstalled and
|
||||||
|
the volume structure is freed.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - the Volume that is to be reference checked and unlocked.
|
||||||
|
OFile - the OFile whose permanent error code is to be set.
|
||||||
|
EfiStatus - error code to be set.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Clean up the volume successfully.
|
||||||
|
Others - Cleaning up of the volume is failed.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
//
|
||||||
|
// Flag the OFile
|
||||||
|
//
|
||||||
|
if (OFile != NULL) {
|
||||||
|
FatSetVolumeError (OFile, EfiStatus);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Clean up any dangling OFiles that don't have IFiles
|
||||||
|
// we don't check return status here because we want the
|
||||||
|
// volume be cleaned up even the volume is invalid.
|
||||||
|
//
|
||||||
|
FatCheckVolumeRef (Volume);
|
||||||
|
if (Volume->Valid) {
|
||||||
|
//
|
||||||
|
// Update the free hint info. Volume->FreeInfoPos != 0
|
||||||
|
// indicates this a FAT32 volume
|
||||||
|
//
|
||||||
|
if (Volume->FreeInfoValid && Volume->FatDirty && Volume->FreeInfoPos) {
|
||||||
|
Status = FatDiskIo (Volume, WRITE_DISK, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Update that the volume is not dirty
|
||||||
|
//
|
||||||
|
if (Volume->FatDirty && Volume->FatType != FAT12) {
|
||||||
|
Volume->FatDirty = FALSE;
|
||||||
|
Status = FatAccessVolumeDirty (Volume, WRITE_FAT, &Volume->NotDirtyValue);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Flush all dirty cache entries to disk
|
||||||
|
//
|
||||||
|
Status = FatVolumeFlushCache (Volume);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the volume is cleared , remove it.
|
||||||
|
// The only time volume be invalidated is in DriverBindingStop.
|
||||||
|
//
|
||||||
|
if (Volume->Root == NULL && !Volume->Valid) {
|
||||||
|
//
|
||||||
|
// Free the volume structure
|
||||||
|
//
|
||||||
|
FatFreeVolume (Volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EfiStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatSetVolumeError (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN EFI_STATUS Status
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the OFile and its child OFile with the error Status
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The OFile whose permanent error code is to be set.
|
||||||
|
Status - Error code to be set.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
LIST_ENTRY *Link;
|
||||||
|
FAT_OFILE *ChildOFile;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If this OFile doesn't already have an error, set one
|
||||||
|
//
|
||||||
|
if (!EFI_ERROR (OFile->Error)) {
|
||||||
|
OFile->Error = Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Set the error on each child OFile
|
||||||
|
//
|
||||||
|
for (Link = OFile->ChildHead.ForwardLink; Link != &OFile->ChildHead; Link = Link->ForwardLink) {
|
||||||
|
ChildOFile = OFILE_FROM_CHILDLINK (Link);
|
||||||
|
FatSetVolumeError (ChildOFile, Status);
|
||||||
|
}
|
||||||
|
}
|
217
FatPkg/EnhancedFatDxe/Hash.c
Normal file
217
FatPkg/EnhancedFatDxe/Hash.c
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
Hash.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Hash table operations
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
UINT32
|
||||||
|
FatHashLongName (
|
||||||
|
IN CHAR16 *LongNameString
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get hash value for long name.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
LongNameString - The long name string to be hashed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
HashValue.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINT32 HashValue;
|
||||||
|
CHAR16 UpCasedLongFileName[EFI_PATH_STRING_LENGTH];
|
||||||
|
StrCpy (UpCasedLongFileName, LongNameString);
|
||||||
|
FatStrUpr (UpCasedLongFileName);
|
||||||
|
gBS->CalculateCrc32 (UpCasedLongFileName, StrSize (UpCasedLongFileName), &HashValue);
|
||||||
|
return (HashValue & HASH_TABLE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
UINT32
|
||||||
|
FatHashShortName (
|
||||||
|
IN CHAR8 *ShortNameString
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get hash value for short name.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ShortNameString - The short name string to be hashed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
HashValue
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINT32 HashValue;
|
||||||
|
gBS->CalculateCrc32 (ShortNameString, FAT_NAME_LEN, &HashValue);
|
||||||
|
return (HashValue & HASH_TABLE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
FAT_DIRENT **
|
||||||
|
FatLongNameHashSearch (
|
||||||
|
IN FAT_ODIR *ODir,
|
||||||
|
IN CHAR16 *LongNameString
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Search the long name hash table for the directory entry.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ODir - The directory to be searched.
|
||||||
|
LongNameString - The long name string to search.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The previous long name hash node of the directory entry.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_DIRENT **PreviousHashNode;
|
||||||
|
for (PreviousHashNode = &ODir->LongNameHashTable[FatHashLongName (LongNameString)];
|
||||||
|
*PreviousHashNode != NULL;
|
||||||
|
PreviousHashNode = &(*PreviousHashNode)->LongNameForwardLink
|
||||||
|
) {
|
||||||
|
if (FatStriCmp (LongNameString, (*PreviousHashNode)->FileString) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PreviousHashNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
FAT_DIRENT **
|
||||||
|
FatShortNameHashSearch (
|
||||||
|
IN FAT_ODIR *ODir,
|
||||||
|
IN CHAR8 *ShortNameString
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Search the short name hash table for the directory entry.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ODir - The directory to be searched.
|
||||||
|
ShortNameString - The short name string to search.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
The previous short name hash node of the directory entry.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_DIRENT **PreviousHashNode;
|
||||||
|
for (PreviousHashNode = &ODir->ShortNameHashTable[FatHashShortName (ShortNameString)];
|
||||||
|
*PreviousHashNode != NULL;
|
||||||
|
PreviousHashNode = &(*PreviousHashNode)->ShortNameForwardLink
|
||||||
|
) {
|
||||||
|
if (CompareMem (ShortNameString, (*PreviousHashNode)->Entry.FileName, FAT_NAME_LEN) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PreviousHashNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatInsertToHashTable (
|
||||||
|
IN FAT_ODIR *ODir,
|
||||||
|
IN FAT_DIRENT *DirEnt
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Insert directory entry to hash table.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ODir - The parent directory.
|
||||||
|
DirEnt - The directory entry node.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_DIRENT **HashTable;
|
||||||
|
UINT32 HashTableIndex;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Insert hash table index for short name
|
||||||
|
//
|
||||||
|
HashTableIndex = FatHashShortName (DirEnt->Entry.FileName);
|
||||||
|
HashTable = ODir->ShortNameHashTable;
|
||||||
|
DirEnt->ShortNameForwardLink = HashTable[HashTableIndex];
|
||||||
|
HashTable[HashTableIndex] = DirEnt;
|
||||||
|
//
|
||||||
|
// Insert hash table index for long name
|
||||||
|
//
|
||||||
|
HashTableIndex = FatHashLongName (DirEnt->FileString);
|
||||||
|
HashTable = ODir->LongNameHashTable;
|
||||||
|
DirEnt->LongNameForwardLink = HashTable[HashTableIndex];
|
||||||
|
HashTable[HashTableIndex] = DirEnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatDeleteFromHashTable (
|
||||||
|
IN FAT_ODIR *ODir,
|
||||||
|
IN FAT_DIRENT *DirEnt
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Delete directory entry from hash table.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ODir - The parent directory.
|
||||||
|
DirEnt - The directory entry node.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
*FatShortNameHashSearch (ODir, DirEnt->Entry.FileName) = DirEnt->ShortNameForwardLink;
|
||||||
|
*FatLongNameHashSearch (ODir, DirEnt->FileString) = DirEnt->LongNameForwardLink;
|
||||||
|
}
|
625
FatPkg/EnhancedFatDxe/Info.c
Normal file
625
FatPkg/EnhancedFatDxe/Info.c
Normal file
@ -0,0 +1,625 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
Info.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Routines dealing with setting/getting file/volume info
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetVolumeInfo (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetVolumeInfo (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN OUT UINTN BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetOrGetInfo (
|
||||||
|
IN BOOLEAN IsSet,
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
IN EFI_GUID *Type,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
IN OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetFileInfo (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the open file's info into Buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing file info.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the file info successfully.
|
||||||
|
EFI_BUFFER_TOO_SMALL - The buffer is too small.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
return FatGetDirEntInfo (OFile->Volume, OFile->DirEnt, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetVolumeInfo (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the volume's info into Buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing volume info.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the volume info successfully.
|
||||||
|
EFI_BUFFER_TOO_SMALL - The buffer is too small.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN Size;
|
||||||
|
UINTN NameSize;
|
||||||
|
UINTN ResultSize;
|
||||||
|
CHAR16 Name[FAT_NAME_LEN + 1];
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FILE_SYSTEM_INFO *Info;
|
||||||
|
UINT8 ClusterAlignment;
|
||||||
|
|
||||||
|
Size = SIZE_OF_EFI_FILE_SYSTEM_INFO;
|
||||||
|
Status = FatGetVolumeEntry (Volume, Name);
|
||||||
|
NameSize = StrSize (Name);
|
||||||
|
ResultSize = Size + NameSize;
|
||||||
|
ClusterAlignment = Volume->ClusterAlignment;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If we don't have valid info, compute it now
|
||||||
|
//
|
||||||
|
FatComputeFreeInfo (Volume);
|
||||||
|
|
||||||
|
Status = EFI_BUFFER_TOO_SMALL;
|
||||||
|
if (*BufferSize >= ResultSize) {
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
Info = Buffer;
|
||||||
|
ZeroMem (Info, SIZE_OF_EFI_FILE_SYSTEM_INFO);
|
||||||
|
|
||||||
|
Info->Size = ResultSize;
|
||||||
|
Info->ReadOnly = Volume->ReadOnly;
|
||||||
|
Info->BlockSize = (UINT32) Volume->ClusterSize;
|
||||||
|
Info->VolumeSize = LShiftU64 (Volume->MaxCluster, ClusterAlignment);
|
||||||
|
Info->FreeSpace = LShiftU64 (
|
||||||
|
Volume->FatInfoSector.FreeInfo.ClusterCount,
|
||||||
|
ClusterAlignment
|
||||||
|
);
|
||||||
|
CopyMem ((CHAR8 *) Buffer + Size, Name, NameSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
*BufferSize = ResultSize;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetVolumeLabelInfo (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the volume's label info into Buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing volume's label info.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the volume's label info successfully.
|
||||||
|
EFI_BUFFER_TOO_SMALL - The buffer is too small.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN Size;
|
||||||
|
UINTN NameSize;
|
||||||
|
UINTN ResultSize;
|
||||||
|
CHAR16 Name[FAT_NAME_LEN + 1];
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO;
|
||||||
|
Status = FatGetVolumeEntry (Volume, Name);
|
||||||
|
NameSize = StrSize (Name);
|
||||||
|
ResultSize = Size + NameSize;
|
||||||
|
|
||||||
|
Status = EFI_BUFFER_TOO_SMALL;
|
||||||
|
if (*BufferSize >= ResultSize) {
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
CopyMem ((CHAR8 *) Buffer + Size, Name, NameSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
*BufferSize = ResultSize;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetVolumeInfo (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the volume's info.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing the new volume info.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the volume info successfully.
|
||||||
|
EFI_BAD_BUFFER_SIZE - The buffer size is error.
|
||||||
|
EFI_WRITE_PROTECTED - The volume is read only.
|
||||||
|
other - An error occurred when operation the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_FILE_SYSTEM_INFO *Info;
|
||||||
|
|
||||||
|
Info = (EFI_FILE_SYSTEM_INFO *) Buffer;
|
||||||
|
|
||||||
|
if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + 2 || Info->Size > BufferSize) {
|
||||||
|
return EFI_BAD_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FatSetVolumeEntry (Volume, Info->VolumeLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetVolumeLabelInfo (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the volume's label info
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing the new volume label info.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the volume label info successfully.
|
||||||
|
EFI_WRITE_PROTECTED - The disk is write protected.
|
||||||
|
EFI_BAD_BUFFER_SIZE - The buffer size is error.
|
||||||
|
other - An error occurred when operation the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info;
|
||||||
|
|
||||||
|
Info = (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *) Buffer;
|
||||||
|
|
||||||
|
if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 2) {
|
||||||
|
return EFI_BAD_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FatSetVolumeEntry (Volume, Info->VolumeLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetFileInfo (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN FAT_IFILE *IFile,
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the file info.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
IFile - The instance of the open file.
|
||||||
|
OFile - The open file.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing the new file info.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the file info successfully.
|
||||||
|
EFI_ACCESS_DENIED - It is the root directory
|
||||||
|
or the directory attribute bit can not change
|
||||||
|
or try to change a directory size
|
||||||
|
or something else.
|
||||||
|
EFI_UNSUPPORTED - The new file size is larger than 4GB.
|
||||||
|
EFI_WRITE_PROTECTED - The disk is write protected.
|
||||||
|
EFI_BAD_BUFFER_SIZE - The buffer size is error.
|
||||||
|
EFI_INVALID_PARAMETER - The time info or attributes info is error.
|
||||||
|
EFI_OUT_OF_RESOURCES - Can not allocate new memory.
|
||||||
|
EFI_VOLUME_CORRUPTED - The volume is corrupted.
|
||||||
|
other - An error occurred when operation the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FILE_INFO *NewInfo;
|
||||||
|
FAT_OFILE *DotOFile;
|
||||||
|
FAT_OFILE *Parent;
|
||||||
|
CHAR16 NewFileName[EFI_PATH_STRING_LENGTH];
|
||||||
|
EFI_TIME ZeroTime;
|
||||||
|
FAT_DIRENT *DirEnt;
|
||||||
|
FAT_DIRENT *TempDirEnt;
|
||||||
|
UINT8 NewAttribute;
|
||||||
|
BOOLEAN ReadOnly;
|
||||||
|
|
||||||
|
ZeroMem (&ZeroTime, sizeof (EFI_TIME));
|
||||||
|
Parent = OFile->Parent;
|
||||||
|
DirEnt = OFile->DirEnt;
|
||||||
|
//
|
||||||
|
// If this is the root directory, we can't make any updates
|
||||||
|
//
|
||||||
|
if (Parent == NULL) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Make sure there's a valid input buffer
|
||||||
|
//
|
||||||
|
NewInfo = Buffer;
|
||||||
|
if (BufferSize < SIZE_OF_EFI_FILE_INFO + 2 || NewInfo->Size > BufferSize) {
|
||||||
|
return EFI_BAD_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnly = (BOOLEAN)(IFile->ReadOnly || (DirEnt->Entry.Attributes & EFI_FILE_READ_ONLY));
|
||||||
|
//
|
||||||
|
// if a zero time is specified, then the original time is preserved
|
||||||
|
//
|
||||||
|
if (CompareMem (&ZeroTime, &NewInfo->CreateTime, sizeof (EFI_TIME)) != 0) {
|
||||||
|
if (!FatIsValidTime (&NewInfo->CreateTime)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReadOnly) {
|
||||||
|
FatEfiTimeToFatTime (&NewInfo->CreateTime, &DirEnt->Entry.FileCreateTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareMem (&ZeroTime, &NewInfo->ModificationTime, sizeof (EFI_TIME)) != 0) {
|
||||||
|
if (!FatIsValidTime (&NewInfo->ModificationTime)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ReadOnly) {
|
||||||
|
FatEfiTimeToFatTime (&NewInfo->ModificationTime, &DirEnt->Entry.FileModificationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile->PreserveLastModification = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NewInfo->Attribute & (~EFI_FILE_VALID_ATTR)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewAttribute = (UINT8) NewInfo->Attribute;
|
||||||
|
//
|
||||||
|
// Can not change the directory attribute bit
|
||||||
|
//
|
||||||
|
if ((NewAttribute ^ DirEnt->Entry.Attributes) & EFI_FILE_DIRECTORY) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Set the current attributes even if the IFile->ReadOnly is TRUE
|
||||||
|
//
|
||||||
|
DirEnt->Entry.Attributes = (UINT8) ((DirEnt->Entry.Attributes &~EFI_FILE_VALID_ATTR) | NewAttribute);
|
||||||
|
//
|
||||||
|
// Open the filename and see if it refers to an existing file
|
||||||
|
//
|
||||||
|
Status = FatLocateOFile (&Parent, NewInfo->FileName, DirEnt->Entry.Attributes, NewFileName);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*NewFileName != 0) {
|
||||||
|
//
|
||||||
|
// File was not found. We do not allow rename of the current directory if
|
||||||
|
// there are open files below the current directory
|
||||||
|
//
|
||||||
|
if (!IsListEmpty (&OFile->ChildHead) || Parent == OFile) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReadOnly) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatRemoveDirEnt (OFile->Parent, DirEnt);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Create new dirent
|
||||||
|
//
|
||||||
|
Status = FatCreateDirEnt (Parent, NewFileName, DirEnt->Entry.Attributes, &TempDirEnt);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatCloneDirEnt (TempDirEnt, DirEnt);
|
||||||
|
FatFreeDirEnt (DirEnt);
|
||||||
|
DirEnt = TempDirEnt;
|
||||||
|
DirEnt->OFile = OFile;
|
||||||
|
OFile->DirEnt = DirEnt;
|
||||||
|
OFile->Parent = Parent;
|
||||||
|
RemoveEntryList (&OFile->ChildLink);
|
||||||
|
InsertHeadList (&Parent->ChildHead, &OFile->ChildLink);
|
||||||
|
//
|
||||||
|
// If this is a directory, synchronize its dot directory entry
|
||||||
|
//
|
||||||
|
if (OFile->ODir != NULL) {
|
||||||
|
//
|
||||||
|
// Syncronize its dot entry
|
||||||
|
//
|
||||||
|
FatResetODirCursor (OFile);
|
||||||
|
ASSERT (OFile->Parent != NULL);
|
||||||
|
for (DotOFile = OFile; DotOFile != OFile->Parent->Parent; DotOFile = DotOFile->Parent) {
|
||||||
|
Status = FatGetNextDirEnt (OFile, &DirEnt);
|
||||||
|
if (EFI_ERROR (Status) || DirEnt == NULL || !FatIsDotDirEnt (DirEnt)) {
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatCloneDirEnt (DirEnt, DotOFile->DirEnt);
|
||||||
|
Status = FatStoreDirEnt (OFile, DirEnt);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the file is renamed, we should append the ARCHIVE attribute
|
||||||
|
//
|
||||||
|
OFile->Archive = TRUE;
|
||||||
|
} else if (Parent != OFile) {
|
||||||
|
//
|
||||||
|
// filename is to a different filename that already exists
|
||||||
|
//
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the file size has changed, apply it
|
||||||
|
//
|
||||||
|
if (NewInfo->FileSize != OFile->FileSize) {
|
||||||
|
if (OFile->ODir != NULL || ReadOnly) {
|
||||||
|
//
|
||||||
|
// If this is a directory or the file is read only, we can't change the file size
|
||||||
|
//
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NewInfo->FileSize > OFile->FileSize) {
|
||||||
|
Status = FatExpandOFile (OFile, NewInfo->FileSize);
|
||||||
|
} else {
|
||||||
|
Status = FatTruncateOFile (OFile, (UINTN) NewInfo->FileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatUpdateDirEntClusterSizeInfo (OFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile->Dirty = TRUE;
|
||||||
|
return FatOFileFlush (OFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetOrGetInfo (
|
||||||
|
IN BOOLEAN IsSet,
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
IN EFI_GUID *Type,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
IN OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set or Get the some types info of the file into Buffer
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
IsSet - TRUE:The access is set, else is get
|
||||||
|
FHand - The handle of file
|
||||||
|
Type - The type of the info
|
||||||
|
BufferSize - Size of Buffer
|
||||||
|
Buffer - Buffer containing volume info
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the info successfully
|
||||||
|
EFI_DEVICE_ERROR - Can not find the OFile for the file
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
IFile = IFILE_FROM_FHAND (FHand);
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
|
||||||
|
Status = OFile->Error;
|
||||||
|
if (Status == EFI_NOT_FOUND) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatAcquireLock ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Verify the file handle isn't in an error state
|
||||||
|
//
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Get the proper information based on the request
|
||||||
|
//
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
if (IsSet) {
|
||||||
|
if (Volume->ReadOnly) {
|
||||||
|
Status = EFI_WRITE_PROTECTED;
|
||||||
|
} else {
|
||||||
|
if (CompareGuid (Type, &gEfiFileInfoGuid)) {
|
||||||
|
Status = FatSetFileInfo (Volume, IFile, OFile, *BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareGuid (Type, &gEfiFileSystemInfoGuid)) {
|
||||||
|
Status = FatSetVolumeInfo (Volume, *BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
|
||||||
|
Status = FatSetVolumeLabelInfo (Volume, *BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (CompareGuid (Type, &gEfiFileInfoGuid)) {
|
||||||
|
Status = FatGetFileInfo (OFile, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareGuid (Type, &gEfiFileSystemInfoGuid)) {
|
||||||
|
Status = FatGetVolumeInfo (Volume, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareGuid (Type, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
|
||||||
|
Status = FatGetVolumeLabelInfo (Volume, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatCleanupVolume (Volume, NULL, Status);
|
||||||
|
|
||||||
|
FatReleaseLock ();
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatGetInfo (
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
IN EFI_GUID *Type,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the some types info of the file into Buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - The handle of file.
|
||||||
|
Type - The type of the info.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing volume info.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the info successfully.
|
||||||
|
EFI_DEVICE_ERROR - Can not find the OFile for the file.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
return FatSetOrGetInfo (FALSE, FHand, Type, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatSetInfo (
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
IN EFI_GUID *Type,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the some types info of the file into Buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - The handle of file.
|
||||||
|
Type - The type of the info.
|
||||||
|
BufferSize - Size of Buffer
|
||||||
|
Buffer - Buffer containing volume info.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the info successfully.
|
||||||
|
EFI_DEVICE_ERROR - Can not find the OFile for the file.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
return FatSetOrGetInfo (TRUE, FHand, Type, &BufferSize, Buffer);
|
||||||
|
}
|
431
FatPkg/EnhancedFatDxe/Init.c
Normal file
431
FatPkg/EnhancedFatDxe/Init.c
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
Init.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Initialization routines
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatAllocateVolume (
|
||||||
|
IN EFI_HANDLE Handle,
|
||||||
|
IN EFI_DISK_IO_PROTOCOL *DiskIo,
|
||||||
|
IN EFI_BLOCK_IO_PROTOCOL *BlockIo
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Allocates volume structure, detects FAT file system, installs protocol,
|
||||||
|
and initialize cache.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Handle - The handle of parent device.
|
||||||
|
DiskIo - The DiskIo of parent device.
|
||||||
|
BlockIo - The BlockIo of parent devicel
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Allocate a new volume successfully.
|
||||||
|
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
|
||||||
|
Others - Allocating a new volume failed.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
BOOLEAN LockedByMe;
|
||||||
|
LockedByMe = FALSE;
|
||||||
|
//
|
||||||
|
// Allocate a volume structure
|
||||||
|
//
|
||||||
|
Volume = AllocateZeroPool (sizeof (FAT_VOLUME));
|
||||||
|
if (Volume == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Acquire the lock.
|
||||||
|
// If caller has already acquired the lock, cannot lock it again.
|
||||||
|
//
|
||||||
|
if (!FatIsLocked ()) {
|
||||||
|
FatAcquireLock ();
|
||||||
|
LockedByMe = TRUE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Initialize the structure
|
||||||
|
//
|
||||||
|
Volume->Signature = FAT_VOLUME_SIGNATURE;
|
||||||
|
Volume->Handle = Handle;
|
||||||
|
Volume->DiskIo = DiskIo;
|
||||||
|
Volume->BlockIo = BlockIo;
|
||||||
|
Volume->MediaId = BlockIo->Media->MediaId;
|
||||||
|
Volume->ReadOnly = BlockIo->Media->ReadOnly;
|
||||||
|
Volume->VolumeInterface.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
|
||||||
|
Volume->VolumeInterface.OpenVolume = FatOpenVolume;
|
||||||
|
InitializeListHead (&Volume->CheckRef);
|
||||||
|
InitializeListHead (&Volume->DirCacheList);
|
||||||
|
//
|
||||||
|
// Initialize Root Directory entry
|
||||||
|
//
|
||||||
|
Volume->RootDirEnt.FileString = Volume->RootFileString;
|
||||||
|
Volume->RootDirEnt.Entry.Attributes = FAT_ATTRIBUTE_DIRECTORY;
|
||||||
|
//
|
||||||
|
// Check to see if there's a file system on the volume
|
||||||
|
//
|
||||||
|
Status = FatOpenDevice (Volume);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Initialize cache
|
||||||
|
//
|
||||||
|
Status = FatInitializeDiskCache (Volume);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Install our protocol interfaces on the device's handle
|
||||||
|
//
|
||||||
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||||
|
&Volume->Handle,
|
||||||
|
&gEfiSimpleFileSystemProtocolGuid,
|
||||||
|
&Volume->VolumeInterface,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Volume installed
|
||||||
|
//
|
||||||
|
DEBUG ((EFI_D_INIT, "%HInstalled Fat filesystem on %x%N\n", Handle));
|
||||||
|
Volume->Valid = TRUE;
|
||||||
|
|
||||||
|
Done:
|
||||||
|
//
|
||||||
|
// Unlock if locked by myself.
|
||||||
|
//
|
||||||
|
if (LockedByMe) {
|
||||||
|
FatReleaseLock ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
FatFreeVolume (Volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatAbandonVolume (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Called by FatDriverBindingStop(), Abandon the volume.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - The volume to be abandoned.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Abandoned the volume successfully.
|
||||||
|
Others - Can not uninstall the protocol interfaces.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
BOOLEAN LockedByMe;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Uninstall the protocol interface.
|
||||||
|
//
|
||||||
|
if (Volume->Handle != NULL) {
|
||||||
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||||
|
Volume->Handle,
|
||||||
|
&gEfiSimpleFileSystemProtocolGuid,
|
||||||
|
&Volume->VolumeInterface,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LockedByMe = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Acquire the lock.
|
||||||
|
// If the caller has already acquired the lock (which
|
||||||
|
// means we are in the process of some Fat operation),
|
||||||
|
// we can not acquire again.
|
||||||
|
//
|
||||||
|
if (!FatIsLocked ()) {
|
||||||
|
LockedByMe = TRUE;
|
||||||
|
FatAcquireLock ();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// The volume is still being used. Hence, set error flag for all OFiles still in
|
||||||
|
// use. In two cases, we could get here. One is EFI_MEDIA_CHANGED, the other is
|
||||||
|
// EFI_NO_MEDIA.
|
||||||
|
//
|
||||||
|
if (Volume->Root != NULL) {
|
||||||
|
FatSetVolumeError (
|
||||||
|
Volume->Root,
|
||||||
|
Volume->BlockIo->Media->MediaPresent ? EFI_MEDIA_CHANGED : EFI_NO_MEDIA
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Volume->Valid = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Release the lock.
|
||||||
|
// If locked by me, this means DriverBindingStop is NOT
|
||||||
|
// called within an on-going Fat operation, so we should
|
||||||
|
// take responsibility to cleanup and free the volume.
|
||||||
|
// Otherwise, the DriverBindingStop is called within an on-going
|
||||||
|
// Fat operation, we shouldn't check reference, so just let outer
|
||||||
|
// FatCleanupVolume do the task.
|
||||||
|
//
|
||||||
|
if (LockedByMe) {
|
||||||
|
FatCleanupVolume (Volume, NULL, EFI_SUCCESS);
|
||||||
|
FatReleaseLock ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatOpenDevice (
|
||||||
|
IN OUT FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Detects FAT file system on Disk and set relevant fields of Volume
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - The volume structure.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The Fat File System is detected successfully
|
||||||
|
EFI_UNSUPPORTED - The volume is not FAT file system.
|
||||||
|
EFI_VOLUME_CORRUPTED - The volume is corrupted.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT32 BlockSize;
|
||||||
|
UINT32 DirtyMask;
|
||||||
|
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||||
|
FAT_BOOT_SECTOR FatBs;
|
||||||
|
FAT_VOLUME_TYPE FatType;
|
||||||
|
UINTN RootDirSectors;
|
||||||
|
UINTN FatLba;
|
||||||
|
UINTN RootLba;
|
||||||
|
UINTN FirstClusterLba;
|
||||||
|
UINTN Sectors;
|
||||||
|
UINTN SectorsPerFat;
|
||||||
|
UINT8 SectorsPerClusterAlignment;
|
||||||
|
UINT8 BlockAlignment;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read the FAT_BOOT_SECTOR BPB info
|
||||||
|
// This is the only part of FAT code that uses parent DiskIo,
|
||||||
|
// Others use FatDiskIo which utilizes a Cache.
|
||||||
|
//
|
||||||
|
DiskIo = Volume->DiskIo;
|
||||||
|
Status = DiskIo->ReadDisk (DiskIo, Volume->MediaId, 0, sizeof (FatBs), &FatBs);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((EFI_D_INIT, "FatOpenDevice: read of part_lba failed %r\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatType = FatUndefined;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use LargeSectors if Sectors is 0
|
||||||
|
//
|
||||||
|
Sectors = FatBs.FatBsb.Sectors;
|
||||||
|
if (Sectors == 0) {
|
||||||
|
Sectors = FatBs.FatBsb.LargeSectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
SectorsPerFat = FatBs.FatBsb.SectorsPerFat;
|
||||||
|
if (SectorsPerFat == 0) {
|
||||||
|
SectorsPerFat = FatBs.FatBse.Fat32Bse.LargeSectorsPerFat;
|
||||||
|
FatType = FAT32;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Is boot sector a fat sector?
|
||||||
|
// (Note that so far we only know if the sector is FAT32 or not, we don't
|
||||||
|
// know if the sector is Fat16 or Fat12 until later when we can compute
|
||||||
|
// the volume size)
|
||||||
|
//
|
||||||
|
if (FatBs.FatBsb.ReservedSectors == 0 || FatBs.FatBsb.NumFats == 0 || Sectors == 0) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((FatBs.FatBsb.SectorSize & (FatBs.FatBsb.SectorSize - 1)) != 0) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockAlignment = (UINT8) HighBitSet32 (FatBs.FatBsb.SectorSize);
|
||||||
|
if (BlockAlignment > MAX_BLOCK_ALIGNMENT || BlockAlignment < MIN_BLOCK_ALIGNMENT) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((FatBs.FatBsb.SectorsPerCluster & (FatBs.FatBsb.SectorsPerCluster - 1)) != 0) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
SectorsPerClusterAlignment = (UINT8) HighBitSet32 (FatBs.FatBsb.SectorsPerCluster);
|
||||||
|
if (SectorsPerClusterAlignment > MAX_SECTORS_PER_CLUSTER_ALIGNMENT) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FatBs.FatBsb.Media <= 0xf7 &&
|
||||||
|
FatBs.FatBsb.Media != 0xf0 &&
|
||||||
|
FatBs.FatBsb.Media != 0x00 &&
|
||||||
|
FatBs.FatBsb.Media != 0x01
|
||||||
|
) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Initialize fields the volume information for this FatType
|
||||||
|
//
|
||||||
|
if (FatType != FAT32) {
|
||||||
|
if (FatBs.FatBsb.RootEntries == 0) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Unpack fat12, fat16 info
|
||||||
|
//
|
||||||
|
Volume->RootEntries = FatBs.FatBsb.RootEntries;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// If this is fat32, refuse to mount mirror-disabled volumes
|
||||||
|
//
|
||||||
|
if ((SectorsPerFat == 0 || FatBs.FatBse.Fat32Bse.FsVersion != 0) || (FatBs.FatBse.Fat32Bse.ExtendedFlags & 0x80)) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Unpack fat32 info
|
||||||
|
//
|
||||||
|
Volume->RootCluster = FatBs.FatBse.Fat32Bse.RootDirFirstCluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volume->NumFats = FatBs.FatBsb.NumFats;
|
||||||
|
//
|
||||||
|
// Compute some fat locations
|
||||||
|
//
|
||||||
|
BlockSize = FatBs.FatBsb.SectorSize;
|
||||||
|
RootDirSectors = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (BlockSize - 1)) / BlockSize;
|
||||||
|
|
||||||
|
FatLba = FatBs.FatBsb.ReservedSectors;
|
||||||
|
RootLba = FatBs.FatBsb.NumFats * SectorsPerFat + FatLba;
|
||||||
|
FirstClusterLba = RootLba + RootDirSectors;
|
||||||
|
|
||||||
|
Volume->FatPos = FatLba * BlockSize;
|
||||||
|
Volume->FatSize = SectorsPerFat * BlockSize;
|
||||||
|
|
||||||
|
Volume->VolumeSize = LShiftU64 (Sectors, BlockAlignment);
|
||||||
|
Volume->RootPos = LShiftU64 (RootLba, BlockAlignment);
|
||||||
|
Volume->FirstClusterPos = LShiftU64 (FirstClusterLba, BlockAlignment);
|
||||||
|
Volume->MaxCluster = (Sectors - FirstClusterLba) >> SectorsPerClusterAlignment;
|
||||||
|
Volume->ClusterAlignment = (UINT8)(BlockAlignment + SectorsPerClusterAlignment);
|
||||||
|
Volume->ClusterSize = (UINTN)1 << (Volume->ClusterAlignment);
|
||||||
|
|
||||||
|
//
|
||||||
|
// If this is not a fat32, determine if it's a fat16 or fat12
|
||||||
|
//
|
||||||
|
if (FatType != FAT32) {
|
||||||
|
if (Volume->MaxCluster >= FAT_MAX_FAT16_CLUSTER) {
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatType = Volume->MaxCluster < FAT_MAX_FAT12_CLUSTER ? FAT12 : FAT16;
|
||||||
|
//
|
||||||
|
// fat12 & fat16 fat-entries are 2 bytes
|
||||||
|
//
|
||||||
|
Volume->FatEntrySize = sizeof (UINT16);
|
||||||
|
DirtyMask = FAT16_DIRTY_MASK;
|
||||||
|
} else {
|
||||||
|
if (Volume->MaxCluster < FAT_MAX_FAT16_CLUSTER) {
|
||||||
|
return EFI_VOLUME_CORRUPTED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// fat32 fat-entries are 4 bytes
|
||||||
|
//
|
||||||
|
Volume->FatEntrySize = sizeof (UINT32);
|
||||||
|
DirtyMask = FAT32_DIRTY_MASK;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Get the DirtyValue and NotDirtyValue
|
||||||
|
// We should keep the initial value as the NotDirtyValue
|
||||||
|
// in case the volume is dirty already
|
||||||
|
//
|
||||||
|
if (FatType != FAT12) {
|
||||||
|
Status = FatAccessVolumeDirty (Volume, READ_DISK, &Volume->NotDirtyValue);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volume->DirtyValue = Volume->NotDirtyValue & DirtyMask;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If present, read the fat hint info
|
||||||
|
//
|
||||||
|
if (FatType == FAT32) {
|
||||||
|
Volume->FreeInfoPos = FatBs.FatBse.Fat32Bse.FsInfoSector * BlockSize;
|
||||||
|
if (FatBs.FatBse.Fat32Bse.FsInfoSector != 0) {
|
||||||
|
FatDiskIo (Volume, READ_DISK, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector);
|
||||||
|
if (Volume->FatInfoSector.Signature == FAT_INFO_SIGNATURE &&
|
||||||
|
Volume->FatInfoSector.InfoBeginSignature == FAT_INFO_BEGIN_SIGNATURE &&
|
||||||
|
Volume->FatInfoSector.InfoEndSignature == FAT_INFO_END_SIGNATURE &&
|
||||||
|
Volume->FatInfoSector.FreeInfo.ClusterCount <= Volume->MaxCluster
|
||||||
|
) {
|
||||||
|
Volume->FreeInfoValid = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Just make up a FreeInfo.NextCluster for use by allocate cluster
|
||||||
|
//
|
||||||
|
if (FAT_MIN_CLUSTER > Volume->FatInfoSector.FreeInfo.NextCluster ||
|
||||||
|
Volume->FatInfoSector.FreeInfo.NextCluster > Volume->MaxCluster + 1
|
||||||
|
) {
|
||||||
|
Volume->FatInfoSector.FreeInfo.NextCluster = FAT_MIN_CLUSTER;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We are now defining FAT Type
|
||||||
|
//
|
||||||
|
Volume->FatType = FatType;
|
||||||
|
ASSERT (FatType != FatUndefined);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
409
FatPkg/EnhancedFatDxe/Misc.c
Normal file
409
FatPkg/EnhancedFatDxe/Misc.c
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
Misc.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Miscellaneous functions
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatAccessVolumeDirty (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN IO_MODE IoMode,
|
||||||
|
IN VOID *DirtyValue
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the volume as dirty or not
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
IoMode - The access mode.
|
||||||
|
DirtyValue - Set the volume as dirty or not.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the new FAT entry value sucessfully.
|
||||||
|
other - An error occurred when operation the FAT entries.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
UINTN WriteCount;
|
||||||
|
|
||||||
|
WriteCount = Volume->FatEntrySize;
|
||||||
|
return FatDiskIo (Volume, IoMode, Volume->FatPos + WriteCount, WriteCount, DirtyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatDiskIo (
|
||||||
|
IN FAT_VOLUME *Volume,
|
||||||
|
IN IO_MODE IoMode,
|
||||||
|
IN UINT64 Offset,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
IN OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
General disk access function
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - FAT file system volume.
|
||||||
|
IoMode - The access mode (disk read/write or cache access).
|
||||||
|
Offset - The starting byte offset to read from.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing read data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The operation is performed successfully.
|
||||||
|
EFI_VOLUME_CORRUPTED - The accesss is
|
||||||
|
Others - The status of read/write the disk
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_DISK_IO_PROTOCOL *DiskIo;
|
||||||
|
EFI_DISK_READ IoFunction;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Verify the IO is in devices range
|
||||||
|
//
|
||||||
|
Status = EFI_VOLUME_CORRUPTED;
|
||||||
|
if (Offset + BufferSize <= Volume->VolumeSize) {
|
||||||
|
if (CACHE_ENABLED (IoMode)) {
|
||||||
|
//
|
||||||
|
// Access cache
|
||||||
|
//
|
||||||
|
Status = FatAccessCache (Volume, CACHE_TYPE (IoMode), RAW_ACCESS (IoMode), Offset, BufferSize, Buffer);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Access disk directly
|
||||||
|
//
|
||||||
|
DiskIo = Volume->DiskIo;
|
||||||
|
IoFunction = (IoMode == READ_DISK) ? DiskIo->ReadDisk : DiskIo->WriteDisk;
|
||||||
|
Status = IoFunction (DiskIo, Volume->MediaId, Offset, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Volume->DiskError = TRUE;
|
||||||
|
DEBUG ((EFI_D_INFO, "FatDiskIo: error %r\n", Status));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatAcquireLock (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Lock the volume.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EfiAcquireLock (&FatFsLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
FatIsLocked (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the locking status of the volume.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
TRUE - The volume is locked.
|
||||||
|
FALSE - The volume is not locked.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
return (BOOLEAN) (FatFsLock.Lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatReleaseLock (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Unlock the volume.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Null.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EfiReleaseLock (&FatFsLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatFreeDirEnt (
|
||||||
|
IN FAT_DIRENT *DirEnt
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Free directory entry.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DirEnt - The directory entry to be freed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
if (DirEnt->FileString != NULL) {
|
||||||
|
FreePool (DirEnt->FileString);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (DirEnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatFreeVolume (
|
||||||
|
IN FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Free volume structure (including the contents of directory cache and disk cache).
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Volume - The volume structure to be freed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Free disk cache
|
||||||
|
//
|
||||||
|
if (Volume->CacheBuffer != NULL) {
|
||||||
|
FreePool (Volume->CacheBuffer);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Free directory cache
|
||||||
|
//
|
||||||
|
FatCleanupODirCache (Volume);
|
||||||
|
FreePool (Volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatEfiTimeToFatTime (
|
||||||
|
IN EFI_TIME *ETime,
|
||||||
|
OUT FAT_DATE_TIME *FTime
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Translate EFI time to FAT time.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
ETime - The time of EFI_TIME.
|
||||||
|
FTime - The time of FAT_DATE_TIME.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// ignores timezone info in source ETime
|
||||||
|
//
|
||||||
|
if (ETime->Year > 1980) {
|
||||||
|
FTime->Date.Year = (UINT16) (ETime->Year - 1980);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ETime->Year >= 1980 + FAT_MAX_YEAR_FROM_1980) {
|
||||||
|
FTime->Date.Year = FAT_MAX_YEAR_FROM_1980;
|
||||||
|
}
|
||||||
|
|
||||||
|
FTime->Date.Month = ETime->Month;
|
||||||
|
FTime->Date.Day = ETime->Day;
|
||||||
|
FTime->Time.Hour = ETime->Hour;
|
||||||
|
FTime->Time.Minute = ETime->Minute;
|
||||||
|
FTime->Time.DoubleSecond = (UINT16) (ETime->Second / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatFatTimeToEfiTime (
|
||||||
|
IN FAT_DATE_TIME *FTime,
|
||||||
|
OUT EFI_TIME *ETime
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Translate Fat time to EFI time.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FTime - The time of FAT_DATE_TIME.
|
||||||
|
ETime - The time of EFI_TIME.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
ETime->Year = (UINT16) (FTime->Date.Year + 1980);
|
||||||
|
ETime->Month = (UINT8) FTime->Date.Month;
|
||||||
|
ETime->Day = (UINT8) FTime->Date.Day;
|
||||||
|
ETime->Hour = (UINT8) FTime->Time.Hour;
|
||||||
|
ETime->Minute = (UINT8) FTime->Time.Minute;
|
||||||
|
ETime->Second = (UINT8) (FTime->Time.DoubleSecond * 2);
|
||||||
|
ETime->Nanosecond = 0;
|
||||||
|
ETime->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
|
||||||
|
ETime->Daylight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FatGetCurrentFatTime (
|
||||||
|
OUT FAT_DATE_TIME *FatNow
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get Current FAT time.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FatNow - Current FAT time.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_TIME Now;
|
||||||
|
gRT->GetTime (&Now, NULL);
|
||||||
|
FatEfiTimeToFatTime (&Now, FatNow);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
FatIsValidTime (
|
||||||
|
IN EFI_TIME *Time
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Check whether a time is valid.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Time - The time of EFI_TIME.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
TRUE - The time is valid.
|
||||||
|
FALSE - The time is not valid.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
static UINT8 MonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
|
UINTN Day;
|
||||||
|
BOOLEAN ValidTime;
|
||||||
|
|
||||||
|
ValidTime = TRUE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the fields for range problems
|
||||||
|
// Fat can only support from 1980
|
||||||
|
//
|
||||||
|
if (Time->Year < 1980 ||
|
||||||
|
Time->Month < 1 ||
|
||||||
|
Time->Month > 12 ||
|
||||||
|
Time->Day < 1 ||
|
||||||
|
Time->Day > 31 ||
|
||||||
|
Time->Hour > 23 ||
|
||||||
|
Time->Minute > 59 ||
|
||||||
|
Time->Second > 59 ||
|
||||||
|
Time->Nanosecond > 999999999
|
||||||
|
) {
|
||||||
|
|
||||||
|
ValidTime = FALSE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Perform a more specific check of the day of the month
|
||||||
|
//
|
||||||
|
Day = MonthDays[Time->Month - 1];
|
||||||
|
if (Time->Month == 2 && IS_LEAP_YEAR (Time->Year)) {
|
||||||
|
Day += 1;
|
||||||
|
//
|
||||||
|
// 1 extra day this month
|
||||||
|
//
|
||||||
|
}
|
||||||
|
if (Time->Day > Day) {
|
||||||
|
ValidTime = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ValidTime;
|
||||||
|
}
|
285
FatPkg/EnhancedFatDxe/Open.c
Normal file
285
FatPkg/EnhancedFatDxe/Open.c
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005 - 2007, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
open.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Routines dealing with file open
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatAllocateIFile (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
OUT FAT_IFILE **PtrIFile
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Create an Open instance for the existing OFile.
|
||||||
|
The IFile of the newly opened file is passed out.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The file that serves as a starting reference point.
|
||||||
|
PtrIFile - The newly generated IFile instance.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_OUT_OF_RESOURCES - Can not allocate the memory for the IFile
|
||||||
|
EFI_SUCCESS - Create the new IFile for the OFile successfully
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
|
||||||
|
ASSERT_VOLUME_LOCKED (OFile->Volume);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate a new open instance
|
||||||
|
//
|
||||||
|
IFile = AllocateZeroPool (sizeof (FAT_IFILE));
|
||||||
|
if (IFile == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFile->Signature = FAT_IFILE_SIGNATURE;
|
||||||
|
|
||||||
|
CopyMem (&(IFile->Handle), &FatFileInterface, sizeof (EFI_FILE));
|
||||||
|
|
||||||
|
IFile->OFile = OFile;
|
||||||
|
InsertTailList (&OFile->Opens, &IFile->Link);
|
||||||
|
|
||||||
|
*PtrIFile = IFile;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatOFileOpen (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
OUT FAT_IFILE **NewIFile,
|
||||||
|
IN CHAR16 *FileName,
|
||||||
|
IN UINT64 OpenMode,
|
||||||
|
IN UINT8 Attributes
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Open a file for a file name relative to an existing OFile.
|
||||||
|
The IFile of the newly opened file is passed out.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The file that serves as a starting reference point.
|
||||||
|
NewIFile - The newly generated IFile instance.
|
||||||
|
FileName - The file name relative to the OFile.
|
||||||
|
OpenMode - Open mode.
|
||||||
|
Attributes - Attributes to set if the file is created.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Open the file successfully.
|
||||||
|
EFI_INVALID_PARAMETER - The open mode is conflict with the attributes
|
||||||
|
or the file name is not valid.
|
||||||
|
EFI_NOT_FOUND - Conficts between dir intention and attribute.
|
||||||
|
EFI_WRITE_PROTECTED - Can't open for write if the volume is read only.
|
||||||
|
EFI_ACCESS_DENIED - If the file's attribute is read only, and the
|
||||||
|
open is for read-write fail it.
|
||||||
|
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
CHAR16 NewFileName[EFI_PATH_STRING_LENGTH];
|
||||||
|
FAT_DIRENT *DirEnt;
|
||||||
|
UINT8 FileAttributes;
|
||||||
|
BOOLEAN WriteMode;
|
||||||
|
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
ASSERT_VOLUME_LOCKED (Volume);
|
||||||
|
WriteMode = (BOOLEAN) (OpenMode & EFI_FILE_MODE_WRITE);
|
||||||
|
if (Volume->ReadOnly && WriteMode) {
|
||||||
|
return EFI_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Verify the source file handle isn't in an error state
|
||||||
|
//
|
||||||
|
Status = OFile->Error;
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Get new OFile for the file
|
||||||
|
//
|
||||||
|
Status = FatLocateOFile (&OFile, FileName, Attributes, NewFileName);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*NewFileName != 0) {
|
||||||
|
//
|
||||||
|
// If there's a remaining part of the name, then we had
|
||||||
|
// better be creating the file in the directory
|
||||||
|
//
|
||||||
|
if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatCreateDirEnt (OFile, NewFileName, Attributes, &DirEnt);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatOpenDirEnt (OFile, DirEnt);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile = DirEnt->OFile;
|
||||||
|
if (OFile->ODir != NULL) {
|
||||||
|
//
|
||||||
|
// If we just created a directory, we need to create "." and ".."
|
||||||
|
//
|
||||||
|
Status = FatCreateDotDirEnts (OFile);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the file's attribute is read only, and the open is for
|
||||||
|
// read-write, then the access is denied.
|
||||||
|
//
|
||||||
|
FileAttributes = OFile->DirEnt->Entry.Attributes;
|
||||||
|
if ((FileAttributes & EFI_FILE_READ_ONLY) != 0 && (FileAttributes & FAT_ATTRIBUTE_DIRECTORY) == 0 && WriteMode) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Create an open instance of the OFile
|
||||||
|
//
|
||||||
|
Status = FatAllocateIFile (OFile, NewIFile);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*NewIFile)->ReadOnly = (BOOLEAN)!WriteMode;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "FSOpen: Open '%S' %r\n", FileName, Status));
|
||||||
|
return FatOFileFlush (OFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatOpen (
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
OUT EFI_FILE **NewHandle,
|
||||||
|
IN CHAR16 *FileName,
|
||||||
|
IN UINT64 OpenMode,
|
||||||
|
IN UINT64 Attributes
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Implements Open() of Simple File System Protocol.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - File handle of the file serves as a starting reference point.
|
||||||
|
NewHandle - Handle of the file that is newly opened.
|
||||||
|
FileName - File name relative to FHand.
|
||||||
|
OpenMode - Open mode.
|
||||||
|
Attributes - Attributes to set if the file is created.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty.
|
||||||
|
The OpenMode is not supported.
|
||||||
|
The Attributes is not the valid attributes.
|
||||||
|
EFI_OUT_OF_RESOURCES - Can not allocate the memory for file string.
|
||||||
|
EFI_SUCCESS - Open the file successfully.
|
||||||
|
Others - The status of open file.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
FAT_IFILE *NewIFile;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Perform some parameter checking
|
||||||
|
//
|
||||||
|
if (FileName == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Check for a valid mode
|
||||||
|
//
|
||||||
|
switch (OpenMode) {
|
||||||
|
case EFI_FILE_MODE_READ:
|
||||||
|
case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
|
||||||
|
case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Check for valid attributes
|
||||||
|
//
|
||||||
|
if (Attributes & (~EFI_FILE_VALID_ATTR)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Can't open for create and apply the read only attribute
|
||||||
|
//
|
||||||
|
if ((OpenMode & EFI_FILE_MODE_CREATE) && (Attributes & EFI_FILE_READ_ONLY)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFile = IFILE_FROM_FHAND (FHand);
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lock
|
||||||
|
//
|
||||||
|
FatAcquireLock ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open the file
|
||||||
|
//
|
||||||
|
Status = FatOFileOpen (OFile, &NewIFile, FileName, OpenMode, (UINT8) Attributes);
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the file was opened, return the handle to the caller
|
||||||
|
//
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
*NewHandle = &NewIFile->Handle;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Unlock
|
||||||
|
//
|
||||||
|
Status = FatCleanupVolume (OFile->Volume, NULL, Status);
|
||||||
|
FatReleaseLock ();
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
80
FatPkg/EnhancedFatDxe/OpenVolume.c
Normal file
80
FatPkg/EnhancedFatDxe/OpenVolume.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
OpenVolume.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
OpenVolume() function of Simple File System Protocol
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatOpenVolume (
|
||||||
|
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
|
||||||
|
OUT EFI_FILE **File
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Implements Simple File System Protocol interface function OpenVolume().
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
This - Calling context.
|
||||||
|
File - the Root Directory of the volume.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_OUT_OF_RESOURCES - Can not allocate the memory.
|
||||||
|
EFI_VOLUME_CORRUPTED - The FAT type is error.
|
||||||
|
EFI_SUCCESS - Open the volume successfully.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
|
||||||
|
Volume = VOLUME_FROM_VOL_INTERFACE (This);
|
||||||
|
FatAcquireLock ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open Root file
|
||||||
|
//
|
||||||
|
Status = FatOpenDirEnt (NULL, &Volume->RootDirEnt);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Open a new instance to the root
|
||||||
|
//
|
||||||
|
Status = FatAllocateIFile (Volume->Root, &IFile);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
*File = &IFile->Handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
|
||||||
|
Status = FatCleanupVolume (Volume, Volume->Root, Status);
|
||||||
|
FatReleaseLock ();
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
612
FatPkg/EnhancedFatDxe/ReadWrite.c
Normal file
612
FatPkg/EnhancedFatDxe/ReadWrite.c
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 2005, Intel Corporation
|
||||||
|
All rights reserved. This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
ReadWrite.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Functions that perform file read/write
|
||||||
|
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "Fat.h"
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatGetPosition (
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
OUT UINT64 *Position
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the file's position of the file.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - The handle of file.
|
||||||
|
Position - The file's position of the file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the info successfully.
|
||||||
|
EFI_DEVICE_ERROR - Can not find the OFile for the file.
|
||||||
|
EFI_UNSUPPORTED - The open file is not a file.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
|
||||||
|
IFile = IFILE_FROM_FHAND (FHand);
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
|
||||||
|
if (OFile->Error == EFI_NOT_FOUND) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OFile->ODir != NULL) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*Position = IFile->Position;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatSetPosition (
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
IN UINT64 Position
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Set the file's position of the file.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - The handle of file.
|
||||||
|
Position - The file's position of the file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the info successfully.
|
||||||
|
EFI_DEVICE_ERROR - Can not find the OFile for the file.
|
||||||
|
EFI_UNSUPPORTED - Set a directory with a not-zero position.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
|
||||||
|
IFile = IFILE_FROM_FHAND (FHand);
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
|
||||||
|
if (OFile->Error == EFI_NOT_FOUND) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If this is a directory, we can only set back to position 0
|
||||||
|
//
|
||||||
|
if (OFile->ODir != NULL) {
|
||||||
|
if (Position != 0) {
|
||||||
|
//
|
||||||
|
// Reset current directory cursor;
|
||||||
|
//
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatResetODirCursor (OFile);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Set the position
|
||||||
|
//
|
||||||
|
if (Position == -1) {
|
||||||
|
Position = OFile->FileSize;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Set the position
|
||||||
|
//
|
||||||
|
IFile->Position = Position;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatIFileReadDir (
|
||||||
|
IN FAT_IFILE *IFile,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the file info from the open file of the IFile into Buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
IFile - The instance of the open file.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing read data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the file info successfully.
|
||||||
|
other - An error occurred when operation the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
FAT_ODIR *ODir;
|
||||||
|
FAT_DIRENT *DirEnt;
|
||||||
|
UINT32 CurrentPos;
|
||||||
|
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
ODir = OFile->ODir;
|
||||||
|
CurrentPos = ((UINT32) IFile->Position) / sizeof (FAT_DIRECTORY_ENTRY);
|
||||||
|
|
||||||
|
//
|
||||||
|
// We need to relocate the directory
|
||||||
|
//
|
||||||
|
if (CurrentPos < ODir->CurrentPos) {
|
||||||
|
//
|
||||||
|
// The directory cursor has been modified by another IFile, we reset the cursor
|
||||||
|
//
|
||||||
|
FatResetODirCursor (OFile);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We seek the next directory entry's position
|
||||||
|
//
|
||||||
|
do {
|
||||||
|
Status = FatGetNextDirEnt (OFile, &DirEnt);
|
||||||
|
if (EFI_ERROR (Status) || DirEnt == NULL) {
|
||||||
|
//
|
||||||
|
// Something error occurred or reach the end of directory,
|
||||||
|
// return 0 buffersize
|
||||||
|
//
|
||||||
|
*BufferSize = 0;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
} while (ODir->CurrentPos <= CurrentPos);
|
||||||
|
Status = FatGetDirEntInfo (OFile->Volume, DirEnt, BufferSize, Buffer);
|
||||||
|
|
||||||
|
Done:
|
||||||
|
//
|
||||||
|
// Update IFile's Position
|
||||||
|
//
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Update IFile->Position, if everything is all right
|
||||||
|
//
|
||||||
|
CurrentPos = ODir->CurrentPos;
|
||||||
|
IFile->Position = (UINT64) (CurrentPos * sizeof (FAT_DIRECTORY_ENTRY));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatIFileAccess (
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
IN IO_MODE IoMode,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
IN OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the file info from the open file of the IFile into Buffer.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - The file handle to access.
|
||||||
|
IoMode - Indicate whether the access mode is reading or writing.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing read data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the file info successfully.
|
||||||
|
EFI_DEVICE_ERROR - Can not find the OFile for the file.
|
||||||
|
EFI_VOLUME_CORRUPTED - The file type of open file is error.
|
||||||
|
EFI_WRITE_PROTECTED - The disk is write protect.
|
||||||
|
EFI_ACCESS_DENIED - The file is read-only.
|
||||||
|
other - An error occurred when operating on the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FAT_IFILE *IFile;
|
||||||
|
FAT_OFILE *OFile;
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
UINT64 EndPosition;
|
||||||
|
|
||||||
|
IFile = IFILE_FROM_FHAND (FHand);
|
||||||
|
OFile = IFile->OFile;
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
|
||||||
|
if (OFile->Error == EFI_NOT_FOUND) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IoMode == READ_DATA) {
|
||||||
|
//
|
||||||
|
// If position is at EOF, then return device error
|
||||||
|
//
|
||||||
|
if (IFile->Position > OFile->FileSize) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Check if the we can write data
|
||||||
|
//
|
||||||
|
if (Volume->ReadOnly) {
|
||||||
|
return EFI_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IFile->ReadOnly) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FatAcquireLock ();
|
||||||
|
|
||||||
|
Status = OFile->Error;
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
if (OFile->ODir != NULL) {
|
||||||
|
//
|
||||||
|
// Access a directory
|
||||||
|
//
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
if (IoMode == READ_DATA) {
|
||||||
|
//
|
||||||
|
// Read a directory is supported
|
||||||
|
//
|
||||||
|
Status = FatIFileReadDir (IFile, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
OFile = NULL;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Access a file
|
||||||
|
//
|
||||||
|
EndPosition = IFile->Position + *BufferSize;
|
||||||
|
if (EndPosition > OFile->FileSize) {
|
||||||
|
//
|
||||||
|
// The position goes beyond the end of file
|
||||||
|
//
|
||||||
|
if (IoMode == READ_DATA) {
|
||||||
|
//
|
||||||
|
// Adjust the actual size read
|
||||||
|
//
|
||||||
|
*BufferSize -= (UINTN) EndPosition - OFile->FileSize;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// We expand the file size of OFile
|
||||||
|
//
|
||||||
|
Status = FatGrowEof (OFile, EndPosition);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Must update the file's info into the file's Directory Entry
|
||||||
|
// and then flush the dirty cache info into disk.
|
||||||
|
//
|
||||||
|
*BufferSize = 0;
|
||||||
|
FatOFileFlush (OFile);
|
||||||
|
OFile = NULL;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
FatUpdateDirEntClusterSizeInfo (OFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatAccessOFile (OFile, IoMode, (UINTN) IFile->Position, BufferSize, Buffer);
|
||||||
|
IFile->Position += *BufferSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = FatCleanupVolume (Volume, OFile, Status);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// On EFI_SUCCESS case, not calling FatCleanupVolume():
|
||||||
|
// 1) The Cache flush operation is avoided to enhance
|
||||||
|
// performance. Caller is responsible to call Flush() when necessary.
|
||||||
|
// 2) The volume dirty bit is probably set already, and is expected to be
|
||||||
|
// cleaned in subsequent Flush() or other operations.
|
||||||
|
// 3) Write operation doesn't affect OFile/IFile structure, so
|
||||||
|
// Reference checking is not necessary.
|
||||||
|
//
|
||||||
|
FatReleaseLock ();
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatRead (
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Get the file info.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - The handle of the file.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing read data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Get the file info successfully.
|
||||||
|
EFI_DEVICE_ERROR - Can not find the OFile for the file.
|
||||||
|
EFI_VOLUME_CORRUPTED - The file type of open file is error.
|
||||||
|
other - An error occurred when operation the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
return FatIFileAccess (FHand, READ_DATA, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatWrite (
|
||||||
|
IN EFI_FILE *FHand,
|
||||||
|
IN OUT UINTN *BufferSize,
|
||||||
|
IN VOID *Buffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Write the content of buffer into files.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
FHand - The handle of the file.
|
||||||
|
BufferSize - Size of Buffer.
|
||||||
|
Buffer - Buffer containing write data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Set the file info successfully.
|
||||||
|
EFI_WRITE_PROTECTED - The disk is write protect.
|
||||||
|
EFI_ACCESS_DENIED - The file is read-only.
|
||||||
|
EFI_DEVICE_ERROR - The OFile is not valid.
|
||||||
|
EFI_UNSUPPORTED - The open file is not a file.
|
||||||
|
- The writing file size is larger than 4GB.
|
||||||
|
other - An error occurred when operation the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
return FatIFileAccess (FHand, WRITE_DATA, BufferSize, Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatAccessOFile (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN IO_MODE IoMode,
|
||||||
|
IN UINTN Position,
|
||||||
|
IN OUT UINTN *DataBufferSize,
|
||||||
|
IN OUT UINT8 *UserBuffer
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This function reads data from a file or writes data to a file.
|
||||||
|
It uses OFile->PosRem to determine how much data can be accessed in one time.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file.
|
||||||
|
IoMode - Indicate whether the access mode is reading or writing.
|
||||||
|
Position - The position where data will be accessed.
|
||||||
|
DataBufferSize - Size of Buffer.
|
||||||
|
UserBuffer - Buffer containing data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Access the data successfully.
|
||||||
|
other - An error occurred when operating on the disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
FAT_VOLUME *Volume;
|
||||||
|
UINTN Len;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN BufferSize;
|
||||||
|
|
||||||
|
BufferSize = *DataBufferSize;
|
||||||
|
Volume = OFile->Volume;
|
||||||
|
ASSERT_VOLUME_LOCKED (Volume);
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
while (BufferSize > 0) {
|
||||||
|
//
|
||||||
|
// Seek the OFile to the file position
|
||||||
|
//
|
||||||
|
Status = FatOFilePosition (OFile, Position, BufferSize);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Clip length to block run
|
||||||
|
//
|
||||||
|
Len = BufferSize > OFile->PosRem ? OFile->PosRem : BufferSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write the data
|
||||||
|
//
|
||||||
|
Status = FatDiskIo (Volume, IoMode, OFile->PosDisk, Len, UserBuffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Data was successfully accessed
|
||||||
|
//
|
||||||
|
Position += Len;
|
||||||
|
UserBuffer += Len;
|
||||||
|
BufferSize -= Len;
|
||||||
|
if (IoMode == WRITE_DATA) {
|
||||||
|
OFile->Dirty = TRUE;
|
||||||
|
OFile->Archive = TRUE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Make sure no outbound occurred
|
||||||
|
//
|
||||||
|
ASSERT (Position <= OFile->FileSize);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Update the number of bytes accessed
|
||||||
|
//
|
||||||
|
*DataBufferSize -= BufferSize;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatExpandOFile (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN UINT64 ExpandedSize
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Expand OFile by appending zero bytes at the end of OFile.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file.
|
||||||
|
ExpandedSize - The number of zero bytes appended at the end of the file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The file is expanded successfully.
|
||||||
|
other - An error occurred when expanding file.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN WritePos;
|
||||||
|
|
||||||
|
WritePos = OFile->FileSize;
|
||||||
|
Status = FatGrowEof (OFile, ExpandedSize);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
Status = FatWriteZeroPool (OFile, WritePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatWriteZeroPool (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN UINTN WritePos
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Write zero pool from the WritePos to the end of OFile.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file to write zero pool.
|
||||||
|
WritePos - The number of zero bytes written.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - Write the zero pool successfully.
|
||||||
|
EFI_OUT_OF_RESOURCES - Not enough memory to perform the operation.
|
||||||
|
other - An error occurred when writing disk.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
VOID *ZeroBuffer;
|
||||||
|
UINTN AppendedSize;
|
||||||
|
UINTN BufferSize;
|
||||||
|
UINTN WriteSize;
|
||||||
|
|
||||||
|
AppendedSize = OFile->FileSize - WritePos;
|
||||||
|
BufferSize = AppendedSize;
|
||||||
|
if (AppendedSize > FAT_MAX_ALLOCATE_SIZE) {
|
||||||
|
//
|
||||||
|
// If the appended size is larger, maybe we can not allocate the whole
|
||||||
|
// memory once. So if the growed size is larger than 10M, we just
|
||||||
|
// allocate 10M memory (one healthy system should have 10M available
|
||||||
|
// memory), and then write the zerobuffer to the file several times.
|
||||||
|
//
|
||||||
|
BufferSize = FAT_MAX_ALLOCATE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroBuffer = AllocateZeroPool (BufferSize);
|
||||||
|
if (ZeroBuffer == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
WriteSize = AppendedSize > BufferSize ? BufferSize : (UINTN) AppendedSize;
|
||||||
|
AppendedSize -= WriteSize;
|
||||||
|
Status = FatAccessOFile (OFile, WRITE_DATA, WritePos, &WriteSize, ZeroBuffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
WritePos += WriteSize;
|
||||||
|
} while (AppendedSize > 0);
|
||||||
|
|
||||||
|
FreePool (ZeroBuffer);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
FatTruncateOFile (
|
||||||
|
IN FAT_OFILE *OFile,
|
||||||
|
IN UINTN TruncatedSize
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Truncate the OFile to smaller file size.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
OFile - The open file.
|
||||||
|
TruncatedSize - The new file size.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
EFI_SUCCESS - The file is truncated successfully.
|
||||||
|
other - An error occurred when truncating file.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
OFile->FileSize = TruncatedSize;
|
||||||
|
return FatShrinkEof (OFile);
|
||||||
|
}
|
324
FatPkg/EnhancedFatDxe/UnicodeCollation.c
Normal file
324
FatPkg/EnhancedFatDxe/UnicodeCollation.c
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
/** @file
|
||||||
|
Unicode Collation Library that hides the trival difference of Unicode Collation
|
||||||
|
and Unicode collation 2 Protocol.
|
||||||
|
|
||||||
|
Copyright (c) 2007, Intel Corporation<BR>
|
||||||
|
All rights reserved. This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <Uefi.h>
|
||||||
|
|
||||||
|
#include <Guid/GlobalVariable.h>
|
||||||
|
#include <Protocol/UnicodeCollation.h>
|
||||||
|
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
|
|
||||||
|
STATIC EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollationInterface = NULL;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
BOOLEAN
|
||||||
|
(* SEARCH_LANG_CODE) (
|
||||||
|
IN CONST CHAR8 *Languages,
|
||||||
|
IN CONST CHAR8 *MatchLangCode
|
||||||
|
);
|
||||||
|
|
||||||
|
struct _UNICODE_INTERFACE {
|
||||||
|
CHAR16 *VariableName;
|
||||||
|
CHAR8 *DefaultLangCode;
|
||||||
|
SEARCH_LANG_CODE SearchLangCode;
|
||||||
|
EFI_GUID *UnicodeProtocolGuid;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _UNICODE_INTERFACE UNICODE_INTERFACE;
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
BOOLEAN
|
||||||
|
SearchIso639LangCode (
|
||||||
|
IN CONST CHAR8 *Languages,
|
||||||
|
IN CONST CHAR8 *MatchLangCode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CONST CHAR8 *LangCode;
|
||||||
|
|
||||||
|
for (LangCode = Languages; *LangCode != '\0'; LangCode += 3) {
|
||||||
|
if (CompareMem (LangCode, MatchLangCode, 3) == 0) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
BOOLEAN
|
||||||
|
SearchRfc3066LangCode (
|
||||||
|
IN CONST CHAR8 *Languages,
|
||||||
|
IN CONST CHAR8 *MatchLangCode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CHAR8 *SubStr;
|
||||||
|
CHAR8 Terminal;
|
||||||
|
|
||||||
|
SubStr = AsciiStrStr (Languages, MatchLangCode);
|
||||||
|
if (SubStr == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubStr != Languages && *(SubStr - 1) != ';') {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal = *(SubStr + AsciiStrLen (MatchLangCode));
|
||||||
|
if (Terminal != '\0' && Terminal != ';') {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED UNICODE_INTERFACE mIso639Lang = {
|
||||||
|
L"Lang",
|
||||||
|
(CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang),
|
||||||
|
SearchIso639LangCode,
|
||||||
|
&gEfiUnicodeCollationProtocolGuid,
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED UNICODE_INTERFACE mRfc3066Lang = {
|
||||||
|
L"PlatformLang",
|
||||||
|
(CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang),
|
||||||
|
SearchRfc3066LangCode,
|
||||||
|
&gEfiUnicodeCollation2ProtocolGuid,
|
||||||
|
};
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
InitializeUnicodeCollationSupportWithConfig (
|
||||||
|
IN EFI_HANDLE AgentHandle,
|
||||||
|
IN UNICODE_INTERFACE *UnicodeInterface
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
CHAR8 Buffer[100];
|
||||||
|
UINTN BufferSize;
|
||||||
|
UINTN Index;
|
||||||
|
CHAR8 *LangCode;
|
||||||
|
UINTN NoHandles;
|
||||||
|
EFI_HANDLE *Handles;
|
||||||
|
EFI_UNICODE_COLLATION_PROTOCOL *Uci;
|
||||||
|
|
||||||
|
LangCode = Buffer;
|
||||||
|
BufferSize = sizeof (Buffer);
|
||||||
|
Status = gRT->GetVariable (
|
||||||
|
UnicodeInterface->VariableName,
|
||||||
|
&gEfiGlobalVariableGuid,
|
||||||
|
NULL,
|
||||||
|
&BufferSize,
|
||||||
|
Buffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
LangCode = UnicodeInterface->DefaultLangCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
UnicodeInterface->UnicodeProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&NoHandles,
|
||||||
|
&Handles
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < NoHandles; Index++) {
|
||||||
|
//
|
||||||
|
// Open Unicode Collation Protocol
|
||||||
|
//
|
||||||
|
Status = gBS->OpenProtocol (
|
||||||
|
Handles[Index],
|
||||||
|
UnicodeInterface->UnicodeProtocolGuid,
|
||||||
|
(VOID **) &Uci,
|
||||||
|
AgentHandle,
|
||||||
|
NULL,
|
||||||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UnicodeInterface->SearchLangCode (Uci->SupportedLanguages, LangCode)) {
|
||||||
|
mUnicodeCollationInterface = Uci;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (Handles);
|
||||||
|
|
||||||
|
return (mUnicodeCollationInterface != NULL)? EFI_SUCCESS : EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize Unicode Collation support.
|
||||||
|
|
||||||
|
@param AgentHandle The handle used to open Unicode Collation (2) protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The Unicode Collation (2) protocol has been successfully located.
|
||||||
|
@retval Others The Unicode Collation (2) protocol has not been located.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitializeUnicodeCollationSupport (
|
||||||
|
IN EFI_HANDLE AgentHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
if (FeaturePcdGet (PcdUnicodeCollation2Support)) {
|
||||||
|
Status = InitializeUnicodeCollationSupportWithConfig (AgentHandle, &mRfc3066Lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FeaturePcdGet (PcdUnicodeCollationSupport) && EFI_ERROR (Status)) {
|
||||||
|
Status = InitializeUnicodeCollationSupportWithConfig (AgentHandle, &mIso639Lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs a case-insensitive comparison of two Null-terminated Unicode strings.
|
||||||
|
|
||||||
|
@param S1 A pointer to a Null-terminated Unicode string.
|
||||||
|
@param S2 A pointer to a Null-terminated Unicode string.
|
||||||
|
|
||||||
|
@retval 0 S1 is equivalent to S2.
|
||||||
|
@retval >0 S1 is lexically greater than S2.
|
||||||
|
@retval <0 S1 is lexically less than S2.
|
||||||
|
**/
|
||||||
|
INTN
|
||||||
|
FatStriCmp (
|
||||||
|
IN CHAR16 *S1,
|
||||||
|
IN CHAR16 *S2
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT (StrSize (S1) != 0);
|
||||||
|
ASSERT (StrSize (S2) != 0);
|
||||||
|
ASSERT (mUnicodeCollationInterface != NULL);
|
||||||
|
|
||||||
|
return mUnicodeCollationInterface->StriColl (
|
||||||
|
mUnicodeCollationInterface,
|
||||||
|
S1,
|
||||||
|
S2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Uppercase a string.
|
||||||
|
|
||||||
|
@param Str The string which will be upper-cased.
|
||||||
|
|
||||||
|
@return None.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FatStrUpr (
|
||||||
|
IN OUT CHAR16 *String
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT (StrSize (String) != 0);
|
||||||
|
ASSERT (mUnicodeCollationInterface != NULL);
|
||||||
|
|
||||||
|
mUnicodeCollationInterface->StrUpr (mUnicodeCollationInterface, String);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Lowercase a string
|
||||||
|
|
||||||
|
@param Str The string which will be lower-cased.
|
||||||
|
|
||||||
|
@return None
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FatStrLwr (
|
||||||
|
IN OUT CHAR16 *String
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT (StrSize (String) != 0);
|
||||||
|
ASSERT (mUnicodeCollationInterface != NULL);
|
||||||
|
|
||||||
|
mUnicodeCollationInterface->StrLwr (mUnicodeCollationInterface, String);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert FAT string to unicode string.
|
||||||
|
|
||||||
|
@param FatSize The size of FAT string.
|
||||||
|
@param Fat The FAT string.
|
||||||
|
@param String The unicode string.
|
||||||
|
|
||||||
|
@return None.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FatFatToStr (
|
||||||
|
IN UINTN FatSize,
|
||||||
|
IN CHAR8 *Fat,
|
||||||
|
OUT CHAR16 *String
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT (Fat != NULL);
|
||||||
|
ASSERT (String != NULL);
|
||||||
|
ASSERT (((UINTN) String & 0x01) != 0);
|
||||||
|
ASSERT (mUnicodeCollationInterface != NULL);
|
||||||
|
|
||||||
|
mUnicodeCollationInterface->FatToStr (mUnicodeCollationInterface, FatSize, Fat, String);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert unicode string to Fat string.
|
||||||
|
|
||||||
|
@param String The unicode string.
|
||||||
|
@param FatSize The size of the FAT string.
|
||||||
|
@param Fat The FAT string.
|
||||||
|
|
||||||
|
@retval TRUE Convert successfully.
|
||||||
|
@retval FALSE Convert error.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
FatStrToFat (
|
||||||
|
IN CHAR16 *String,
|
||||||
|
IN UINTN FatSize,
|
||||||
|
OUT CHAR8 *Fat
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT (Fat != NULL);
|
||||||
|
ASSERT (StrSize (String) != 0);
|
||||||
|
ASSERT (mUnicodeCollationInterface != NULL);
|
||||||
|
|
||||||
|
return mUnicodeCollationInterface->StrToFat (
|
||||||
|
mUnicodeCollationInterface,
|
||||||
|
String,
|
||||||
|
FatSize,
|
||||||
|
Fat
|
||||||
|
);
|
||||||
|
}
|
29
FatPkg/FatPkg.dec
Normal file
29
FatPkg/FatPkg.dec
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#/** @file
|
||||||
|
#
|
||||||
|
# FAT Package
|
||||||
|
#
|
||||||
|
# FAT 32 Driver
|
||||||
|
# Copyright (c) 2007, Intel Corporation.
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials are licensed and made available
|
||||||
|
# under the terms and conditions of the BSD License which accompanies this
|
||||||
|
# distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
#**/
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
DEC_VERSION = 0x00010005
|
||||||
|
PACKAGE_NAME = FatPkg
|
||||||
|
PACKAGE_GUID = 8EA68A2C-99CB-4332-85C6-DD5864EAA674
|
||||||
|
|
||||||
|
[PcdsFeatureFlag.common]
|
||||||
|
gEfiFatPkgTokenSpaceGuid.PcdUnicodeCollationSupport|TRUE|BOOLEAN|0x00010001
|
||||||
|
gEfiFatPkgTokenSpaceGuid.PcdUnicodeCollation2Support|TRUE|BOOLEAN|0x00010002
|
||||||
|
|
||||||
|
[Guids.common]
|
||||||
|
gEfiFatPkgTokenSpaceGuid = {0xc8e92dba, 0x1d92, 0x411f, {0xae, 0xa, 0x1d, 0xbe, 0xd8, 0xf1, 0x32, 0x99}};
|
||||||
|
|
49
FatPkg/FatPkg.dsc
Normal file
49
FatPkg/FatPkg.dsc
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#/** @file
|
||||||
|
#
|
||||||
|
# Build Binary Enhanced Fat Driver Modules
|
||||||
|
#
|
||||||
|
# This Platform file is used to generate the Binary Fat Drivers
|
||||||
|
# for EDK II Prime release.
|
||||||
|
# Copyright (c) 2007, Intel Corporation
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials are licensed and made available
|
||||||
|
# under the terms and conditions of the BSD License which accompanies this
|
||||||
|
# distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
#**/
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
PLATFORM_NAME = Fat
|
||||||
|
PLATFORM_GUID = 25b55dbc-9d0b-4a32-80da-46e1273d622c
|
||||||
|
PLATFORM_VERSION = 0.1
|
||||||
|
DSC_SPECIFICATION = 0x00010005
|
||||||
|
SUPPORTED_ARCHITECTURES = IA32|X64|IPF|EBC
|
||||||
|
OUTPUT_DIRECTORY = Build/Fat
|
||||||
|
BUILD_TARGETS = DEBUG|RELEASE
|
||||||
|
SKUID_IDENTIFIER = DEFAULT
|
||||||
|
|
||||||
|
[LibraryClasses.common]
|
||||||
|
#
|
||||||
|
# Entry Point Libraries
|
||||||
|
#
|
||||||
|
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
|
||||||
|
#
|
||||||
|
# Common Libraries
|
||||||
|
#
|
||||||
|
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||||
|
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
|
||||||
|
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
|
||||||
|
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||||
|
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
|
||||||
|
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
|
||||||
|
MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf
|
||||||
|
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
|
||||||
|
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
|
||||||
|
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
|
||||||
|
|
||||||
|
[Components.common]
|
||||||
|
FatPkg\EnhancedFatDxe\Fat.inf
|
11
FatPkg/License.txt
Normal file
11
FatPkg/License.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Copyright (c) 2006, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
7
FatPkg/ReadMe.txt
Normal file
7
FatPkg/ReadMe.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
EDK II Prime FAT Package
|
||||||
|
|
||||||
|
Build Validation:
|
||||||
|
MYTOOLS(VS2005) IA32 X64 IPF EBC
|
||||||
|
ICC IA32 X64 IPF
|
||||||
|
CYGWINGCC IA32 X64
|
||||||
|
|
Reference in New Issue
Block a user