]>
git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/EnhancedFatDxe/Misc.c
3 Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Miscellaneous functions
30 EFI_FILE_IO_TOKEN
*Token
40 IFile - The instance of the open file.
41 Token - A pointer to the token associated with the transaction.
44 FAT_TASK * - Return the task instance.
49 Task
= AllocateZeroPool (sizeof (*Task
));
51 Task
->Signature
= FAT_TASK_SIGNATURE
;
53 Task
->FileIoToken
= Token
;
54 InitializeListHead (&Task
->Subtasks
);
55 InitializeListHead (&Task
->Link
);
72 Task - The task to be destroyed.
78 Link
= GetFirstNode (&Task
->Subtasks
);
79 while (!IsNull (&Task
->Subtasks
, Link
)) {
80 Subtask
= CR (Link
, FAT_SUBTASK
, Link
, FAT_SUBTASK_SIGNATURE
);
81 Link
= FatDestroySubtask (Subtask
);
83 RemoveEntryList (&Task
->Link
);
88 FatWaitNonblockingTask (
95 Wait all non-blocking requests complete.
99 IFile - The instance of the open file.
102 BOOLEAN TaskQueueEmpty
;
105 EfiAcquireLock (&FatTaskLock
);
106 TaskQueueEmpty
= IsListEmpty (&IFile
->Tasks
);
107 EfiReleaseLock (&FatTaskLock
);
108 } while (!TaskQueueEmpty
);
119 Remove the subtask from subtask list.
123 Subtask - The subtask to be removed.
127 LIST_ENTRY * - The next node in the list.
133 gBS
->CloseEvent (Subtask
->DiskIo2Token
.Event
);
135 Link
= RemoveEntryList (&Subtask
->Link
);
154 IFile - The instance of the open file.
155 Task - The task to be executed.
159 EFI_SUCCESS - The task was executed sucessfully.
160 other - An error occurred when executing the task.
166 FAT_SUBTASK
*Subtask
;
169 // Sometimes the Task doesn't contain any subtasks, signal the event directly.
171 if (IsListEmpty (&Task
->Subtasks
)) {
172 Task
->FileIoToken
->Status
= EFI_SUCCESS
;
173 gBS
->SignalEvent (Task
->FileIoToken
->Event
);
178 EfiAcquireLock (&FatTaskLock
);
179 InsertTailList (&IFile
->Tasks
, &Task
->Link
);
180 EfiReleaseLock (&FatTaskLock
);
182 Status
= EFI_SUCCESS
;
183 for ( Link
= GetFirstNode (&Task
->Subtasks
)
184 ; !IsNull (&Task
->Subtasks
, Link
)
185 ; Link
= GetNextNode (&Task
->Subtasks
, Link
)
187 Subtask
= CR (Link
, FAT_SUBTASK
, Link
, FAT_SUBTASK_SIGNATURE
);
188 if (Subtask
->Write
) {
190 Status
= IFile
->OFile
->Volume
->DiskIo2
->WriteDiskEx (
191 IFile
->OFile
->Volume
->DiskIo2
,
192 IFile
->OFile
->Volume
->MediaId
,
194 &Subtask
->DiskIo2Token
,
199 Status
= IFile
->OFile
->Volume
->DiskIo2
->ReadDiskEx (
200 IFile
->OFile
->Volume
->DiskIo2
,
201 IFile
->OFile
->Volume
->MediaId
,
203 &Subtask
->DiskIo2Token
,
208 if (EFI_ERROR (Status
)) {
213 if (EFI_ERROR (Status
)) {
214 EfiAcquireLock (&FatTaskLock
);
216 // Remove all the remaining subtasks when failure.
217 // We shouldn't remove all the tasks because the non-blocking requests have
218 // been submitted and cannot be canceled.
220 while (!IsNull (&Task
->Subtasks
, Link
)) {
221 Subtask
= CR (Link
, FAT_SUBTASK
, Link
, FAT_SUBTASK_SIGNATURE
);
222 Link
= FatDestroySubtask (Subtask
);
225 if (IsListEmpty (&Task
->Subtasks
)) {
226 RemoveEntryList (&Task
->Link
);
230 // If one or more subtasks have been already submitted, set FileIoToken
231 // to NULL so that the callback won't signal the event.
233 Task
->FileIoToken
= NULL
;
236 EfiReleaseLock (&FatTaskLock
);
243 FatAccessVolumeDirty (
244 IN FAT_VOLUME
*Volume
,
252 Set the volume as dirty or not
256 Volume - FAT file system volume.
257 IoMode - The access mode.
258 DirtyValue - Set the volume as dirty or not.
262 EFI_SUCCESS - Set the new FAT entry value sucessfully.
263 other - An error occurred when operation the FAT entries.
269 WriteCount
= Volume
->FatEntrySize
;
270 return FatDiskIo (Volume
, IoMode
, Volume
->FatPos
+ WriteCount
, WriteCount
, DirtyValue
, NULL
);
274 Invoke a notification event
276 @param Event Event whose notification function is being invoked.
277 @param Context The pointer to the notification function's context,
278 which is implementation-dependent.
283 FatOnAccessComplete (
291 Invoke a notification event
292 case #1. some subtasks are not completed when the FatOpenEx checks the Task->Subtasks
293 - sets Task->SubtaskCollected so callback to signal the event and free the task.
294 case #2. all subtasks are completed when the FatOpenEx checks the Task->Subtasks
295 - FatOpenEx signal the event and free the task.
298 Event - Event whose notification function is being invoked.
299 Context - The pointer to the notification function's context,
300 which is implementation-dependent.
305 FAT_SUBTASK
*Subtask
;
309 // Avoid someone in future breaks the below assumption.
311 ASSERT (EfiGetCurrentTpl () == FatTaskLock
.Tpl
);
313 Subtask
= (FAT_SUBTASK
*) Context
;
314 Task
= Subtask
->Task
;
315 Status
= Subtask
->DiskIo2Token
.TransactionStatus
;
317 ASSERT (Task
->Signature
== FAT_TASK_SIGNATURE
);
318 ASSERT (Subtask
->Signature
== FAT_SUBTASK_SIGNATURE
);
321 // Remove the task unconditionally
323 FatDestroySubtask (Subtask
);
326 // Task->FileIoToken is NULL which means the task will be ignored (just recycle the subtask and task memory).
328 if (Task
->FileIoToken
!= NULL
) {
329 if (IsListEmpty (&Task
->Subtasks
) || EFI_ERROR (Status
)) {
330 Task
->FileIoToken
->Status
= Status
;
331 gBS
->SignalEvent (Task
->FileIoToken
->Event
);
333 // Mark Task->FileIoToken to NULL so that the subtasks belonging to the task will be ignored.
335 Task
->FileIoToken
= NULL
;
339 if (IsListEmpty (&Task
->Subtasks
)) {
340 RemoveEntryList (&Task
->Link
);
347 IN FAT_VOLUME
*Volume
,
358 General disk access function
362 Volume - FAT file system volume.
363 IoMode - The access mode (disk read/write or cache access).
364 Offset - The starting byte offset to read from.
365 BufferSize - Size of Buffer.
366 Buffer - Buffer containing read data.
370 EFI_SUCCESS - The operation is performed successfully.
371 EFI_VOLUME_CORRUPTED - The accesss is
372 Others - The status of read/write the disk
377 EFI_DISK_IO_PROTOCOL
*DiskIo
;
378 EFI_DISK_READ IoFunction
;
379 FAT_SUBTASK
*Subtask
;
382 // Verify the IO is in devices range
384 Status
= EFI_VOLUME_CORRUPTED
;
385 if (Offset
+ BufferSize
<= Volume
->VolumeSize
) {
386 if (CACHE_ENABLED (IoMode
)) {
390 Status
= FatAccessCache (Volume
, CACHE_TYPE (IoMode
), RAW_ACCESS (IoMode
), Offset
, BufferSize
, Buffer
, Task
);
393 // Access disk directly
399 DiskIo
= Volume
->DiskIo
;
400 IoFunction
= (IoMode
== READ_DISK
) ? DiskIo
->ReadDisk
: DiskIo
->WriteDisk
;
401 Status
= IoFunction (DiskIo
, Volume
->MediaId
, Offset
, BufferSize
, Buffer
);
404 // Non-blocking access
406 Subtask
= AllocateZeroPool (sizeof (*Subtask
));
407 if (Subtask
== NULL
) {
408 Status
= EFI_OUT_OF_RESOURCES
;
410 Subtask
->Signature
= FAT_SUBTASK_SIGNATURE
;
411 Subtask
->Task
= Task
;
412 Subtask
->Write
= (BOOLEAN
) (IoMode
== WRITE_DISK
);
413 Subtask
->Offset
= Offset
;
414 Subtask
->Buffer
= Buffer
;
415 Subtask
->BufferSize
= BufferSize
;
416 Status
= gBS
->CreateEvent (
421 &Subtask
->DiskIo2Token
.Event
423 if (!EFI_ERROR (Status
)) {
424 InsertTailList (&Task
->Subtasks
, &Subtask
->Link
);
433 if (EFI_ERROR (Status
)) {
434 Volume
->DiskError
= TRUE
;
435 DEBUG ((EFI_D_ERROR
, "FatDiskIo: error %r\n", Status
));
461 EfiAcquireLock (&FatFsLock
);
465 FatAcquireLockOrFail (
473 If the lock is already in the acquired state, then EFI_ACCESS_DENIED is returned.
474 Otherwise, EFI_SUCCESS is returned.
482 EFI_SUCCESS - The volume is locked.
483 EFI_ACCESS_DENIED - The volume could not be locked because it is already locked.
487 return EfiAcquireLockOrFail (&FatFsLock
);
510 EfiReleaseLock (&FatFsLock
);
515 IN FAT_DIRENT
*DirEnt
521 Free directory entry.
525 DirEnt - The directory entry to be freed.
533 if (DirEnt
->FileString
!= NULL
) {
534 FreePool (DirEnt
->FileString
);
542 IN FAT_VOLUME
*Volume
548 Free volume structure (including the contents of directory cache and disk cache).
552 Volume - The volume structure to be freed.
563 if (Volume
->CacheBuffer
!= NULL
) {
564 FreePool (Volume
->CacheBuffer
);
567 // Free directory cache
569 FatCleanupODirCache (Volume
);
574 FatEfiTimeToFatTime (
576 OUT FAT_DATE_TIME
*FTime
582 Translate EFI time to FAT time.
586 ETime - The time of EFI_TIME.
587 FTime - The time of FAT_DATE_TIME.
596 // ignores timezone info in source ETime
598 if (ETime
->Year
> 1980) {
599 FTime
->Date
.Year
= (UINT16
) (ETime
->Year
- 1980);
602 if (ETime
->Year
>= 1980 + FAT_MAX_YEAR_FROM_1980
) {
603 FTime
->Date
.Year
= FAT_MAX_YEAR_FROM_1980
;
606 FTime
->Date
.Month
= ETime
->Month
;
607 FTime
->Date
.Day
= ETime
->Day
;
608 FTime
->Time
.Hour
= ETime
->Hour
;
609 FTime
->Time
.Minute
= ETime
->Minute
;
610 FTime
->Time
.DoubleSecond
= (UINT16
) (ETime
->Second
/ 2);
614 FatFatTimeToEfiTime (
615 IN FAT_DATE_TIME
*FTime
,
622 Translate Fat time to EFI time.
626 FTime - The time of FAT_DATE_TIME.
627 ETime - The time of EFI_TIME.
635 ETime
->Year
= (UINT16
) (FTime
->Date
.Year
+ 1980);
636 ETime
->Month
= (UINT8
) FTime
->Date
.Month
;
637 ETime
->Day
= (UINT8
) FTime
->Date
.Day
;
638 ETime
->Hour
= (UINT8
) FTime
->Time
.Hour
;
639 ETime
->Minute
= (UINT8
) FTime
->Time
.Minute
;
640 ETime
->Second
= (UINT8
) (FTime
->Time
.DoubleSecond
* 2);
641 ETime
->Nanosecond
= 0;
642 ETime
->TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
647 FatGetCurrentFatTime (
648 OUT FAT_DATE_TIME
*FatNow
654 Get Current FAT time.
658 FatNow - Current FAT time.
669 Status
= gRT
->GetTime (&Now
, NULL
);
670 if (!EFI_ERROR (Status
)) {
671 FatEfiTimeToFatTime (&Now
, FatNow
);
673 ZeroMem (&Now
, sizeof (EFI_TIME
));
677 FatEfiTimeToFatTime (&Now
, FatNow
);
689 Check whether a time is valid.
693 Time - The time of EFI_TIME.
697 TRUE - The time is valid.
698 FALSE - The time is not valid.
702 static UINT8 MonthDays
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
709 // Check the fields for range problems
710 // Fat can only support from 1980
712 if (Time
->Year
< 1980 ||
720 Time
->Nanosecond
> 999999999
727 // Perform a more specific check of the day of the month
729 Day
= MonthDays
[Time
->Month
- 1];
730 if (Time
->Month
== 2 && IS_LEAP_YEAR (Time
->Year
)) {
733 // 1 extra day this month
736 if (Time
->Day
> Day
) {