]>
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
26 UINT8 mMonthDays
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
31 EFI_FILE_IO_TOKEN
*Token
41 IFile - The instance of the open file.
42 Token - A pointer to the token associated with the transaction.
45 FAT_TASK * - Return the task instance.
50 Task
= AllocateZeroPool (sizeof (*Task
));
52 Task
->Signature
= FAT_TASK_SIGNATURE
;
54 Task
->FileIoToken
= Token
;
55 InitializeListHead (&Task
->Subtasks
);
56 InitializeListHead (&Task
->Link
);
73 Task - The task to be destroyed.
79 Link
= GetFirstNode (&Task
->Subtasks
);
80 while (!IsNull (&Task
->Subtasks
, Link
)) {
81 Subtask
= CR (Link
, FAT_SUBTASK
, Link
, FAT_SUBTASK_SIGNATURE
);
82 Link
= FatDestroySubtask (Subtask
);
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.
708 // Check the fields for range problems
709 // Fat can only support from 1980
711 if (Time
->Year
< 1980 ||
719 Time
->Nanosecond
> 999999999
726 // Perform a more specific check of the day of the month
728 Day
= mMonthDays
[Time
->Month
- 1];
729 if (Time
->Month
== 2 && IS_LEAP_YEAR (Time
->Year
)) {
732 // 1 extra day this month
735 if (Time
->Day
> Day
) {