]>
git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/EnhancedFatDxe/Misc.c
2 Miscellaneous functions.
4 Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 UINT8 mMonthDays
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
23 @param IFile - The instance of the open file.
24 @param Token - A pointer to the token associated with the transaction.
26 @return FAT_TASK * - Return the task instance.
32 EFI_FILE_IO_TOKEN
*Token
37 Task
= AllocateZeroPool (sizeof (*Task
));
39 Task
->Signature
= FAT_TASK_SIGNATURE
;
41 Task
->FileIoToken
= Token
;
42 InitializeListHead (&Task
->Subtasks
);
43 InitializeListHead (&Task
->Link
);
52 @param Task - The task to be destroyed.
63 Link
= GetFirstNode (&Task
->Subtasks
);
64 while (!IsNull (&Task
->Subtasks
, Link
)) {
65 Subtask
= CR (Link
, FAT_SUBTASK
, Link
, FAT_SUBTASK_SIGNATURE
);
66 Link
= FatDestroySubtask (Subtask
);
73 Wait all non-blocking requests complete.
75 @param IFile - The instance of the open file.
79 FatWaitNonblockingTask (
83 BOOLEAN TaskQueueEmpty
;
86 EfiAcquireLock (&FatTaskLock
);
87 TaskQueueEmpty
= IsListEmpty (&IFile
->Tasks
);
88 EfiReleaseLock (&FatTaskLock
);
89 } while (!TaskQueueEmpty
);
94 Remove the subtask from subtask list.
96 @param Subtask - The subtask to be removed.
98 @return LIST_ENTRY * - The next node in the list.
108 gBS
->CloseEvent (Subtask
->DiskIo2Token
.Event
);
110 Link
= RemoveEntryList (&Subtask
->Link
);
120 @param IFile - The instance of the open file.
121 @param Task - The task to be executed.
123 @retval EFI_SUCCESS - The task was executed sucessfully.
124 @return other - An error occurred when executing the task.
135 FAT_SUBTASK
*Subtask
;
138 // Sometimes the Task doesn't contain any subtasks, signal the event directly.
140 if (IsListEmpty (&Task
->Subtasks
)) {
141 Task
->FileIoToken
->Status
= EFI_SUCCESS
;
142 gBS
->SignalEvent (Task
->FileIoToken
->Event
);
147 EfiAcquireLock (&FatTaskLock
);
148 InsertTailList (&IFile
->Tasks
, &Task
->Link
);
149 EfiReleaseLock (&FatTaskLock
);
151 Status
= EFI_SUCCESS
;
152 for ( Link
= GetFirstNode (&Task
->Subtasks
)
153 ; !IsNull (&Task
->Subtasks
, Link
)
154 ; Link
= GetNextNode (&Task
->Subtasks
, Link
)
156 Subtask
= CR (Link
, FAT_SUBTASK
, Link
, FAT_SUBTASK_SIGNATURE
);
157 if (Subtask
->Write
) {
159 Status
= IFile
->OFile
->Volume
->DiskIo2
->WriteDiskEx (
160 IFile
->OFile
->Volume
->DiskIo2
,
161 IFile
->OFile
->Volume
->MediaId
,
163 &Subtask
->DiskIo2Token
,
168 Status
= IFile
->OFile
->Volume
->DiskIo2
->ReadDiskEx (
169 IFile
->OFile
->Volume
->DiskIo2
,
170 IFile
->OFile
->Volume
->MediaId
,
172 &Subtask
->DiskIo2Token
,
177 if (EFI_ERROR (Status
)) {
182 if (EFI_ERROR (Status
)) {
183 EfiAcquireLock (&FatTaskLock
);
185 // Remove all the remaining subtasks when failure.
186 // We shouldn't remove all the tasks because the non-blocking requests have
187 // been submitted and cannot be canceled.
189 while (!IsNull (&Task
->Subtasks
, Link
)) {
190 Subtask
= CR (Link
, FAT_SUBTASK
, Link
, FAT_SUBTASK_SIGNATURE
);
191 Link
= FatDestroySubtask (Subtask
);
194 if (IsListEmpty (&Task
->Subtasks
)) {
195 RemoveEntryList (&Task
->Link
);
199 // If one or more subtasks have been already submitted, set FileIoToken
200 // to NULL so that the callback won't signal the event.
202 Task
->FileIoToken
= NULL
;
205 EfiReleaseLock (&FatTaskLock
);
213 Set the volume as dirty or not.
215 @param Volume - FAT file system volume.
216 @param IoMode - The access mode.
217 @param DirtyValue - Set the volume as dirty or not.
219 @retval EFI_SUCCESS - Set the new FAT entry value sucessfully.
220 @return other - An error occurred when operation the FAT entries.
224 FatAccessVolumeDirty (
225 IN FAT_VOLUME
*Volume
,
232 WriteCount
= Volume
->FatEntrySize
;
233 return FatDiskIo (Volume
, IoMode
, Volume
->FatPos
+ WriteCount
, WriteCount
, DirtyValue
, NULL
);
237 Invoke a notification event.
239 @param Event Event whose notification function is being invoked.
240 @param Context The pointer to the notification function's context,
241 which is implementation-dependent.
246 FatOnAccessComplete (
252 FAT_SUBTASK
*Subtask
;
256 // Avoid someone in future breaks the below assumption.
258 ASSERT (EfiGetCurrentTpl () == FatTaskLock
.Tpl
);
260 Subtask
= (FAT_SUBTASK
*) Context
;
261 Task
= Subtask
->Task
;
262 Status
= Subtask
->DiskIo2Token
.TransactionStatus
;
264 ASSERT (Task
->Signature
== FAT_TASK_SIGNATURE
);
265 ASSERT (Subtask
->Signature
== FAT_SUBTASK_SIGNATURE
);
268 // Remove the task unconditionally
270 FatDestroySubtask (Subtask
);
273 // Task->FileIoToken is NULL which means the task will be ignored (just recycle the subtask and task memory).
275 if (Task
->FileIoToken
!= NULL
) {
276 if (IsListEmpty (&Task
->Subtasks
) || EFI_ERROR (Status
)) {
277 Task
->FileIoToken
->Status
= Status
;
278 gBS
->SignalEvent (Task
->FileIoToken
->Event
);
280 // Mark Task->FileIoToken to NULL so that the subtasks belonging to the task will be ignored.
282 Task
->FileIoToken
= NULL
;
286 if (IsListEmpty (&Task
->Subtasks
)) {
287 RemoveEntryList (&Task
->Link
);
294 General disk access function.
296 @param Volume - FAT file system volume.
297 @param IoMode - The access mode (disk read/write or cache access).
298 @param Offset - The starting byte offset to read from.
299 @param BufferSize - Size of Buffer.
300 @param Buffer - Buffer containing read data.
301 @param Task point to task instance.
303 @retval EFI_SUCCESS - The operation is performed successfully.
304 @retval EFI_VOLUME_CORRUPTED - The accesss is
305 @return Others - The status of read/write the disk
310 IN FAT_VOLUME
*Volume
,
319 EFI_DISK_IO_PROTOCOL
*DiskIo
;
320 EFI_DISK_READ IoFunction
;
321 FAT_SUBTASK
*Subtask
;
324 // Verify the IO is in devices range
326 Status
= EFI_VOLUME_CORRUPTED
;
327 if (Offset
+ BufferSize
<= Volume
->VolumeSize
) {
328 if (CACHE_ENABLED (IoMode
)) {
332 Status
= FatAccessCache (Volume
, CACHE_TYPE (IoMode
), RAW_ACCESS (IoMode
), Offset
, BufferSize
, Buffer
, Task
);
335 // Access disk directly
341 DiskIo
= Volume
->DiskIo
;
342 IoFunction
= (IoMode
== ReadDisk
) ? DiskIo
->ReadDisk
: DiskIo
->WriteDisk
;
343 Status
= IoFunction (DiskIo
, Volume
->MediaId
, Offset
, BufferSize
, Buffer
);
346 // Non-blocking access
348 Subtask
= AllocateZeroPool (sizeof (*Subtask
));
349 if (Subtask
== NULL
) {
350 Status
= EFI_OUT_OF_RESOURCES
;
352 Subtask
->Signature
= FAT_SUBTASK_SIGNATURE
;
353 Subtask
->Task
= Task
;
354 Subtask
->Write
= (BOOLEAN
) (IoMode
== WriteDisk
);
355 Subtask
->Offset
= Offset
;
356 Subtask
->Buffer
= Buffer
;
357 Subtask
->BufferSize
= BufferSize
;
358 Status
= gBS
->CreateEvent (
363 &Subtask
->DiskIo2Token
.Event
365 if (!EFI_ERROR (Status
)) {
366 InsertTailList (&Task
->Subtasks
, &Subtask
->Link
);
375 if (EFI_ERROR (Status
)) {
376 Volume
->DiskError
= TRUE
;
377 DEBUG ((EFI_D_ERROR
, "FatDiskIo: error %r\n", Status
));
393 EfiAcquireLock (&FatFsLock
);
399 If the lock is already in the acquired state, then EFI_ACCESS_DENIED is returned.
400 Otherwise, EFI_SUCCESS is returned.
402 @retval EFI_SUCCESS - The volume is locked.
403 @retval EFI_ACCESS_DENIED - The volume could not be locked because it is already locked.
407 FatAcquireLockOrFail (
411 return EfiAcquireLockOrFail (&FatFsLock
);
424 EfiReleaseLock (&FatFsLock
);
429 Free directory entry.
431 @param DirEnt - The directory entry to be freed.
436 IN FAT_DIRENT
*DirEnt
439 if (DirEnt
->FileString
!= NULL
) {
440 FreePool (DirEnt
->FileString
);
448 Free volume structure (including the contents of directory cache and disk cache).
450 @param Volume - The volume structure to be freed.
455 IN FAT_VOLUME
*Volume
461 if (Volume
->CacheBuffer
!= NULL
) {
462 FreePool (Volume
->CacheBuffer
);
465 // Free directory cache
467 FatCleanupODirCache (Volume
);
473 Translate EFI time to FAT time.
475 @param ETime - The time of EFI_TIME.
476 @param FTime - The time of FAT_DATE_TIME.
480 FatEfiTimeToFatTime (
482 OUT FAT_DATE_TIME
*FTime
486 // ignores timezone info in source ETime
488 if (ETime
->Year
> 1980) {
489 FTime
->Date
.Year
= (UINT16
) (ETime
->Year
- 1980);
492 if (ETime
->Year
>= 1980 + FAT_MAX_YEAR_FROM_1980
) {
493 FTime
->Date
.Year
= FAT_MAX_YEAR_FROM_1980
;
496 FTime
->Date
.Month
= ETime
->Month
;
497 FTime
->Date
.Day
= ETime
->Day
;
498 FTime
->Time
.Hour
= ETime
->Hour
;
499 FTime
->Time
.Minute
= ETime
->Minute
;
500 FTime
->Time
.DoubleSecond
= (UINT16
) (ETime
->Second
/ 2);
505 Translate Fat time to EFI time.
507 @param FTime - The time of FAT_DATE_TIME.
508 @param ETime - The time of EFI_TIME..
512 FatFatTimeToEfiTime (
513 IN FAT_DATE_TIME
*FTime
,
517 ETime
->Year
= (UINT16
) (FTime
->Date
.Year
+ 1980);
518 ETime
->Month
= (UINT8
) FTime
->Date
.Month
;
519 ETime
->Day
= (UINT8
) FTime
->Date
.Day
;
520 ETime
->Hour
= (UINT8
) FTime
->Time
.Hour
;
521 ETime
->Minute
= (UINT8
) FTime
->Time
.Minute
;
522 ETime
->Second
= (UINT8
) (FTime
->Time
.DoubleSecond
* 2);
523 ETime
->Nanosecond
= 0;
524 ETime
->TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
530 Get Current FAT time.
532 @param FatNow - Current FAT time.
536 FatGetCurrentFatTime (
537 OUT FAT_DATE_TIME
*FatNow
543 Status
= gRT
->GetTime (&Now
, NULL
);
544 if (!EFI_ERROR (Status
)) {
545 FatEfiTimeToFatTime (&Now
, FatNow
);
547 ZeroMem (&Now
, sizeof (EFI_TIME
));
551 FatEfiTimeToFatTime (&Now
, FatNow
);
557 Check whether a time is valid.
559 @param Time - The time of EFI_TIME.
561 @retval TRUE - The time is valid.
562 @retval FALSE - The time is not valid.
576 // Check the fields for range problems
577 // Fat can only support from 1980
579 if (Time
->Year
< 1980 ||
587 Time
->Nanosecond
> 999999999
594 // Perform a more specific check of the day of the month
596 Day
= mMonthDays
[Time
->Month
- 1];
597 if (Time
->Month
== 2 && IS_LEAP_YEAR (Time
->Year
)) {
600 // 1 extra day this month
603 if (Time
->Day
> Day
) {