-/*++\r
+/** @file\r
+ Miscellaneous functions.\r
\r
Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials are licensed and made available\r
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
\r
-Module Name:\r
-\r
- Misc.c\r
+**/\r
\r
-Abstract:\r
+#include "Fat.h"\r
+UINT8 mMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
\r
- Miscellaneous functions\r
+/**\r
\r
-Revision History\r
+ Create the task\r
\r
---*/\r
+ @param IFile - The instance of the open file.\r
+ @param Token - A pointer to the token associated with the transaction.\r
\r
-#include "Fat.h"\r
+ @return FAT_TASK * - Return the task instance.\r
\r
+**/\r
FAT_TASK *\r
FatCreateTask (\r
FAT_IFILE *IFile,\r
EFI_FILE_IO_TOKEN *Token\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create the task\r
-\r
-Arguments:\r
-\r
- IFile - The instance of the open file.\r
- Token - A pointer to the token associated with the transaction.\r
-\r
-Return:\r
- FAT_TASK * - Return the task instance.\r
-**/\r
{\r
FAT_TASK *Task;\r
\r
return Task;\r
}\r
\r
-VOID\r
-FatDestroyTask (\r
- FAT_TASK *Task\r
- )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
\r
- Destroy the task\r
+ Destroy the task.\r
\r
-Arguments:\r
+ @param Task - The task to be destroyed.\r
\r
- Task - The task to be destroyed.\r
**/\r
+VOID\r
+FatDestroyTask (\r
+ FAT_TASK *Task\r
+ )\r
{\r
LIST_ENTRY *Link;\r
FAT_SUBTASK *Subtask;\r
FreePool (Task);\r
}\r
\r
-VOID\r
-FatWaitNonblockingTask (\r
- FAT_IFILE *IFile\r
- )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
\r
Wait all non-blocking requests complete.\r
\r
-Arguments:\r
+ @param IFile - The instance of the open file.\r
\r
- IFile - The instance of the open file.\r
**/\r
+VOID\r
+FatWaitNonblockingTask (\r
+ FAT_IFILE *IFile\r
+ )\r
{\r
BOOLEAN TaskQueueEmpty;\r
\r
} while (!TaskQueueEmpty);\r
}\r
\r
-LIST_ENTRY *\r
-FatDestroySubtask (\r
- FAT_SUBTASK *Subtask\r
- )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
\r
Remove the subtask from subtask list.\r
\r
-Arguments:\r
-\r
- Subtask - The subtask to be removed.\r
+ @param Subtask - The subtask to be removed.\r
\r
-Returns:\r
+ @return LIST_ENTRY * - The next node in the list.\r
\r
- LIST_ENTRY * - The next node in the list.\r
-\r
---*/\r
+**/\r
+LIST_ENTRY *\r
+FatDestroySubtask (\r
+ FAT_SUBTASK *Subtask\r
+ )\r
{\r
LIST_ENTRY *Link;\r
\r
return Link;\r
}\r
\r
+/**\r
+\r
+ Execute the task.\r
+\r
+ @param IFile - The instance of the open file.\r
+ @param Task - The task to be executed.\r
+\r
+ @retval EFI_SUCCESS - The task was executed sucessfully.\r
+ @return other - An error occurred when executing the task.\r
+\r
+**/\r
EFI_STATUS\r
FatQueueTask (\r
IN FAT_IFILE *IFile,\r
IN FAT_TASK *Task\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Execute the task\r
-\r
-Arguments:\r
-\r
- IFile - The instance of the open file.\r
- Task - The task to be executed.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The task was executed sucessfully.\r
- other - An error occurred when executing the task.\r
-\r
---*/\r
{\r
EFI_STATUS Status;\r
LIST_ENTRY *Link;\r
+ LIST_ENTRY *NextLink;\r
FAT_SUBTASK *Subtask;\r
\r
//\r
EfiReleaseLock (&FatTaskLock);\r
\r
Status = EFI_SUCCESS;\r
- for ( Link = GetFirstNode (&Task->Subtasks)\r
- ; !IsNull (&Task->Subtasks, Link)\r
- ; Link = GetNextNode (&Task->Subtasks, Link)\r
+ //\r
+ // Use NextLink to store the next link of the list, because Link might be remove from the\r
+ // doubly-linked list and get freed in the end of current loop.\r
+ //\r
+ // Also, list operation APIs like IsNull() and GetNextNode() are avoided during the loop, since\r
+ // they may check the validity of doubly-linked lists by traversing them. These APIs cannot\r
+ // handle list elements being removed during the traverse.\r
+ //\r
+ for ( Link = GetFirstNode (&Task->Subtasks), NextLink = GetNextNode (&Task->Subtasks, Link)\r
+ ; Link != &Task->Subtasks\r
+ ; Link = NextLink, NextLink = Link->ForwardLink\r
) {\r
Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);\r
if (Subtask->Write) {\r
return Status;\r
}\r
\r
+/**\r
+\r
+ Set the volume as dirty or not.\r
+\r
+ @param Volume - FAT file system volume.\r
+ @param IoMode - The access mode.\r
+ @param DirtyValue - Set the volume as dirty or not.\r
+\r
+ @retval EFI_SUCCESS - Set the new FAT entry value sucessfully.\r
+ @return other - An error occurred when operation the FAT entries.\r
+\r
+**/\r
EFI_STATUS\r
FatAccessVolumeDirty (\r
IN FAT_VOLUME *Volume,\r
IN IO_MODE IoMode,\r
IN VOID *DirtyValue\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set the volume as dirty or not\r
-\r
-Arguments:\r
-\r
- Volume - FAT file system volume.\r
- IoMode - The access mode.\r
- DirtyValue - Set the volume as dirty or not.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - Set the new FAT entry value sucessfully.\r
- other - An error occurred when operation the FAT entries.\r
-\r
---*/\r
{\r
UINTN WriteCount;\r
\r
}\r
\r
/**\r
- Invoke a notification event\r
+ Invoke a notification event.\r
\r
@param Event Event whose notification function is being invoked.\r
@param Context The pointer to the notification function's context,\r
IN EFI_EVENT Event,\r
IN VOID *Context\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Invoke a notification event\r
- case #1. some subtasks are not completed when the FatOpenEx checks the Task->Subtasks\r
- - sets Task->SubtaskCollected so callback to signal the event and free the task.\r
- case #2. all subtasks are completed when the FatOpenEx checks the Task->Subtasks\r
- - FatOpenEx signal the event and free the task.\r
-Arguments:\r
-\r
- Event - Event whose notification function is being invoked.\r
- Context - The pointer to the notification function's context,\r
- which is implementation-dependent.\r
-\r
---*/\r
{\r
EFI_STATUS Status;\r
FAT_SUBTASK *Subtask;\r
}\r
}\r
\r
+/**\r
+\r
+ General disk access function.\r
+\r
+ @param Volume - FAT file system volume.\r
+ @param IoMode - The access mode (disk read/write or cache access).\r
+ @param Offset - The starting byte offset to read from.\r
+ @param BufferSize - Size of Buffer.\r
+ @param Buffer - Buffer containing read data.\r
+ @param Task point to task instance.\r
+\r
+ @retval EFI_SUCCESS - The operation is performed successfully.\r
+ @retval EFI_VOLUME_CORRUPTED - The accesss is\r
+ @return Others - The status of read/write the disk\r
+\r
+**/\r
EFI_STATUS\r
FatDiskIo (\r
IN FAT_VOLUME *Volume,\r
IN OUT VOID *Buffer,\r
IN FAT_TASK *Task\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- General disk access function\r
-\r
-Arguments:\r
-\r
- Volume - FAT file system volume.\r
- IoMode - The access mode (disk read/write or cache access).\r
- Offset - The starting byte offset to read from.\r
- BufferSize - Size of Buffer.\r
- Buffer - Buffer containing read data.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The operation is performed successfully.\r
- EFI_VOLUME_CORRUPTED - The accesss is\r
- Others - The status of read/write the disk\r
-\r
---*/\r
{\r
EFI_STATUS Status;\r
EFI_DISK_IO_PROTOCOL *DiskIo;\r
// Blocking access\r
//\r
DiskIo = Volume->DiskIo;\r
- IoFunction = (IoMode == READ_DISK) ? DiskIo->ReadDisk : DiskIo->WriteDisk;\r
+ IoFunction = (IoMode == ReadDisk) ? DiskIo->ReadDisk : DiskIo->WriteDisk;\r
Status = IoFunction (DiskIo, Volume->MediaId, Offset, BufferSize, Buffer);\r
} else {\r
//\r
} else {\r
Subtask->Signature = FAT_SUBTASK_SIGNATURE;\r
Subtask->Task = Task;\r
- Subtask->Write = (BOOLEAN) (IoMode == WRITE_DISK);\r
+ Subtask->Write = (BOOLEAN) (IoMode == WriteDisk);\r
Subtask->Offset = Offset;\r
Subtask->Buffer = Buffer;\r
Subtask->BufferSize = BufferSize;\r
return Status;\r
}\r
\r
+/**\r
+\r
+ Lock the volume.\r
+\r
+**/\r
VOID\r
FatAcquireLock (\r
VOID\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Lock the volume.\r
-\r
-Arguments:\r
-\r
- None.\r
-\r
-Returns:\r
-\r
- None.\r
-\r
---*/\r
{\r
EfiAcquireLock (&FatFsLock);\r
}\r
\r
-EFI_STATUS\r
-FatAcquireLockOrFail (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
\r
Lock the volume.\r
If the lock is already in the acquired state, then EFI_ACCESS_DENIED is returned.\r
Otherwise, EFI_SUCCESS is returned.\r
\r
-Arguments:\r
-\r
- None.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The volume is locked.\r
- EFI_ACCESS_DENIED - The volume could not be locked because it is already locked.\r
+ @retval EFI_SUCCESS - The volume is locked.\r
+ @retval EFI_ACCESS_DENIED - The volume could not be locked because it is already locked.\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+FatAcquireLockOrFail (\r
+ VOID\r
+ )\r
{\r
return EfiAcquireLockOrFail (&FatFsLock);\r
}\r
\r
+/**\r
+\r
+ Unlock the volume.\r
+\r
+**/\r
VOID\r
FatReleaseLock (\r
VOID\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Unlock the volume.\r
-\r
-Arguments:\r
-\r
- Null.\r
-\r
-Returns:\r
-\r
- None.\r
-\r
---*/\r
{\r
EfiReleaseLock (&FatFsLock);\r
}\r
\r
-VOID\r
-FatFreeDirEnt (\r
- IN FAT_DIRENT *DirEnt\r
- )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
\r
Free directory entry.\r
\r
-Arguments:\r
-\r
- DirEnt - The directory entry to be freed.\r
-\r
-Returns:\r
-\r
- None.\r
+ @param DirEnt - The directory entry to be freed.\r
\r
---*/\r
+**/\r
+VOID\r
+FatFreeDirEnt (\r
+ IN FAT_DIRENT *DirEnt\r
+ )\r
{\r
if (DirEnt->FileString != NULL) {\r
FreePool (DirEnt->FileString);\r
FreePool (DirEnt);\r
}\r
\r
-VOID\r
-FatFreeVolume (\r
- IN FAT_VOLUME *Volume\r
- )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
\r
Free volume structure (including the contents of directory cache and disk cache).\r
\r
-Arguments:\r
-\r
- Volume - The volume structure to be freed.\r
-\r
-Returns:\r
-\r
- None.\r
+ @param Volume - The volume structure to be freed.\r
\r
---*/\r
+**/\r
+VOID\r
+FatFreeVolume (\r
+ IN FAT_VOLUME *Volume\r
+ )\r
{\r
//\r
// Free disk cache\r
FreePool (Volume);\r
}\r
\r
+/**\r
+\r
+ Translate EFI time to FAT time.\r
+\r
+ @param ETime - The time of EFI_TIME.\r
+ @param FTime - The time of FAT_DATE_TIME.\r
+\r
+**/\r
VOID\r
FatEfiTimeToFatTime (\r
IN EFI_TIME *ETime,\r
OUT FAT_DATE_TIME *FTime\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Translate EFI time to FAT time.\r
-\r
-Arguments:\r
-\r
- ETime - The time of EFI_TIME.\r
- FTime - The time of FAT_DATE_TIME.\r
-\r
-Returns:\r
-\r
- None.\r
-\r
---*/\r
{\r
//\r
// ignores timezone info in source ETime\r
FTime->Time.DoubleSecond = (UINT16) (ETime->Second / 2);\r
}\r
\r
+/**\r
+\r
+ Translate Fat time to EFI time.\r
+\r
+ @param FTime - The time of FAT_DATE_TIME.\r
+ @param ETime - The time of EFI_TIME..\r
+\r
+**/\r
VOID\r
FatFatTimeToEfiTime (\r
IN FAT_DATE_TIME *FTime,\r
OUT EFI_TIME *ETime\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Translate Fat time to EFI time.\r
-\r
-Arguments:\r
-\r
- FTime - The time of FAT_DATE_TIME.\r
- ETime - The time of EFI_TIME.\r
-\r
-Returns:\r
-\r
- None.\r
-\r
---*/\r
{\r
ETime->Year = (UINT16) (FTime->Date.Year + 1980);\r
ETime->Month = (UINT8) FTime->Date.Month;\r
ETime->Daylight = 0;\r
}\r
\r
-VOID\r
-FatGetCurrentFatTime (\r
- OUT FAT_DATE_TIME *FatNow\r
- )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
\r
Get Current FAT time.\r
\r
-Arguments:\r
-\r
- FatNow - Current FAT time.\r
+ @param FatNow - Current FAT time.\r
\r
-Returns:\r
-\r
- None.\r
-\r
---*/\r
+**/\r
+VOID\r
+FatGetCurrentFatTime (\r
+ OUT FAT_DATE_TIME *FatNow\r
+ )\r
{\r
EFI_STATUS Status;\r
EFI_TIME Now;\r
}\r
}\r
\r
-BOOLEAN\r
-FatIsValidTime (\r
- IN EFI_TIME *Time\r
- )\r
-/*++\r
-\r
-Routine Description:\r
+/**\r
\r
Check whether a time is valid.\r
\r
-Arguments:\r
-\r
- Time - The time of EFI_TIME.\r
+ @param Time - The time of EFI_TIME.\r
\r
-Returns:\r
+ @retval TRUE - The time is valid.\r
+ @retval FALSE - The time is not valid.\r
\r
- TRUE - The time is valid.\r
- FALSE - The time is not valid.\r
-\r
---*/\r
+**/\r
+BOOLEAN\r
+FatIsValidTime (\r
+ IN EFI_TIME *Time\r
+ )\r
{\r
- static UINT8 MonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
UINTN Day;\r
BOOLEAN ValidTime;\r
\r
//\r
// Perform a more specific check of the day of the month\r
//\r
- Day = MonthDays[Time->Month - 1];\r
+ Day = mMonthDays[Time->Month - 1];\r
if (Time->Month == 2 && IS_LEAP_YEAR (Time->Year)) {\r
Day += 1;\r
//\r