TianoCore EDK2 master
Loading...
Searching...
No Matches
Misc.c
Go to the documentation of this file.
1
10#include "Fat.h"
11UINT8 mMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
12
25 FAT_IFILE *IFile,
27 )
28{
29 FAT_TASK *Task;
30
31 Task = AllocateZeroPool (sizeof (*Task));
32 if (Task != NULL) {
33 Task->Signature = FAT_TASK_SIGNATURE;
34 Task->IFile = IFile;
35 Task->FileIoToken = Token;
36 InitializeListHead (&Task->Subtasks);
37 InitializeListHead (&Task->Link);
38 }
39
40 return Task;
41}
42
50VOID
52 FAT_TASK *Task
53 )
54{
55 LIST_ENTRY *Link;
56 FAT_SUBTASK *Subtask;
57
58 Link = GetFirstNode (&Task->Subtasks);
59 while (!IsNull (&Task->Subtasks, Link)) {
60 Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);
61 Link = FatDestroySubtask (Subtask);
62 }
63
64 FreePool (Task);
65}
66
74VOID
76 FAT_IFILE *IFile
77 )
78{
79 BOOLEAN TaskQueueEmpty;
80
81 do {
82 EfiAcquireLock (&FatTaskLock);
83 TaskQueueEmpty = IsListEmpty (&IFile->Tasks);
84 EfiReleaseLock (&FatTaskLock);
85 } while (!TaskQueueEmpty);
86}
87
99 FAT_SUBTASK *Subtask
100 )
101{
102 LIST_ENTRY *Link;
103
104 gBS->CloseEvent (Subtask->DiskIo2Token.Event);
105
106 Link = RemoveEntryList (&Subtask->Link);
107 FreePool (Subtask);
108
109 return Link;
110}
111
125 IN FAT_IFILE *IFile,
126 IN FAT_TASK *Task
127 )
128{
129 EFI_STATUS Status;
130 LIST_ENTRY *Link;
131 LIST_ENTRY *NextLink;
132 FAT_SUBTASK *Subtask;
133
134 //
135 // Sometimes the Task doesn't contain any subtasks, signal the event directly.
136 //
137 if (IsListEmpty (&Task->Subtasks)) {
138 Task->FileIoToken->Status = EFI_SUCCESS;
139 gBS->SignalEvent (Task->FileIoToken->Event);
140 FreePool (Task);
141 return EFI_SUCCESS;
142 }
143
144 EfiAcquireLock (&FatTaskLock);
145 InsertTailList (&IFile->Tasks, &Task->Link);
146 EfiReleaseLock (&FatTaskLock);
147
148 Status = EFI_SUCCESS;
149 //
150 // Use NextLink to store the next link of the list, because Link might be remove from the
151 // doubly-linked list and get freed in the end of current loop.
152 //
153 // Also, list operation APIs like IsNull() and GetNextNode() are avoided during the loop, since
154 // they may check the validity of doubly-linked lists by traversing them. These APIs cannot
155 // handle list elements being removed during the traverse.
156 //
157 for ( Link = GetFirstNode (&Task->Subtasks), NextLink = GetNextNode (&Task->Subtasks, Link)
158 ; Link != &Task->Subtasks
159 ; Link = NextLink, NextLink = Link->ForwardLink
160 )
161 {
162 Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);
163 if (Subtask->Write) {
164 Status = IFile->OFile->Volume->DiskIo2->WriteDiskEx (
165 IFile->OFile->Volume->DiskIo2,
166 IFile->OFile->Volume->MediaId,
167 Subtask->Offset,
168 &Subtask->DiskIo2Token,
169 Subtask->BufferSize,
170 Subtask->Buffer
171 );
172 } else {
173 Status = IFile->OFile->Volume->DiskIo2->ReadDiskEx (
174 IFile->OFile->Volume->DiskIo2,
175 IFile->OFile->Volume->MediaId,
176 Subtask->Offset,
177 &Subtask->DiskIo2Token,
178 Subtask->BufferSize,
179 Subtask->Buffer
180 );
181 }
182
183 if (EFI_ERROR (Status)) {
184 break;
185 }
186 }
187
188 if (EFI_ERROR (Status)) {
189 EfiAcquireLock (&FatTaskLock);
190 //
191 // Remove all the remaining subtasks when failure.
192 // We shouldn't remove all the tasks because the non-blocking requests have
193 // been submitted and cannot be canceled.
194 //
195 while (!IsNull (&Task->Subtasks, Link)) {
196 Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);
197 Link = FatDestroySubtask (Subtask);
198 }
199
200 if (IsListEmpty (&Task->Subtasks)) {
201 RemoveEntryList (&Task->Link);
202 FreePool (Task);
203 } else {
204 //
205 // If one or more subtasks have been already submitted, set FileIoToken
206 // to NULL so that the callback won't signal the event.
207 //
208 Task->FileIoToken = NULL;
209 }
210
211 EfiReleaseLock (&FatTaskLock);
212 }
213
214 return Status;
215}
216
231 IN FAT_VOLUME *Volume,
232 IN IO_MODE IoMode,
233 IN VOID *DirtyValue
234 )
235{
236 UINTN WriteCount;
237
238 WriteCount = Volume->FatEntrySize;
239 return FatDiskIo (Volume, IoMode, Volume->FatPos + WriteCount, WriteCount, DirtyValue, NULL);
240}
241
250VOID
251EFIAPI
253 IN EFI_EVENT Event,
254 IN VOID *Context
255 )
256{
257 EFI_STATUS Status;
258 FAT_SUBTASK *Subtask;
259 FAT_TASK *Task;
260
261 //
262 // Avoid someone in future breaks the below assumption.
263 //
264 ASSERT (EfiGetCurrentTpl () == FatTaskLock.Tpl);
265
266 Subtask = (FAT_SUBTASK *)Context;
267 Task = Subtask->Task;
268 Status = Subtask->DiskIo2Token.TransactionStatus;
269
270 ASSERT (Task->Signature == FAT_TASK_SIGNATURE);
271 ASSERT (Subtask->Signature == FAT_SUBTASK_SIGNATURE);
272
273 //
274 // Remove the task unconditionally
275 //
276 FatDestroySubtask (Subtask);
277
278 //
279 // Task->FileIoToken is NULL which means the task will be ignored (just recycle the subtask and task memory).
280 //
281 if (Task->FileIoToken != NULL) {
282 if (IsListEmpty (&Task->Subtasks) || EFI_ERROR (Status)) {
283 Task->FileIoToken->Status = Status;
284 gBS->SignalEvent (Task->FileIoToken->Event);
285 //
286 // Mark Task->FileIoToken to NULL so that the subtasks belonging to the task will be ignored.
287 //
288 Task->FileIoToken = NULL;
289 }
290 }
291
292 if (IsListEmpty (&Task->Subtasks)) {
293 RemoveEntryList (&Task->Link);
294 FreePool (Task);
295 }
296}
297
316 IN FAT_VOLUME *Volume,
317 IN IO_MODE IoMode,
318 IN UINT64 Offset,
319 IN UINTN BufferSize,
320 IN OUT VOID *Buffer,
321 IN FAT_TASK *Task
322 )
323{
324 EFI_STATUS Status;
325 EFI_DISK_IO_PROTOCOL *DiskIo;
326 EFI_DISK_READ IoFunction;
327 FAT_SUBTASK *Subtask;
328
329 //
330 // Verify the IO is in devices range
331 //
332 Status = EFI_VOLUME_CORRUPTED;
333 if (Offset + BufferSize <= Volume->VolumeSize) {
334 if (CACHE_ENABLED (IoMode)) {
335 //
336 // Access cache
337 //
338 Status = FatAccessCache (Volume, CACHE_TYPE (IoMode), RAW_ACCESS (IoMode), Offset, BufferSize, Buffer, Task);
339 } else {
340 //
341 // Access disk directly
342 //
343 if (Task == NULL) {
344 //
345 // Blocking access
346 //
347 DiskIo = Volume->DiskIo;
348 IoFunction = (IoMode == ReadDisk) ? DiskIo->ReadDisk : DiskIo->WriteDisk;
349 Status = IoFunction (DiskIo, Volume->MediaId, Offset, BufferSize, Buffer);
350 } else {
351 //
352 // Non-blocking access
353 //
354 Subtask = AllocateZeroPool (sizeof (*Subtask));
355 if (Subtask == NULL) {
356 Status = EFI_OUT_OF_RESOURCES;
357 } else {
358 Subtask->Signature = FAT_SUBTASK_SIGNATURE;
359 Subtask->Task = Task;
360 Subtask->Write = (BOOLEAN)(IoMode == WriteDisk);
361 Subtask->Offset = Offset;
362 Subtask->Buffer = Buffer;
363 Subtask->BufferSize = BufferSize;
364 Status = gBS->CreateEvent (
365 EVT_NOTIFY_SIGNAL,
366 TPL_NOTIFY,
368 Subtask,
369 &Subtask->DiskIo2Token.Event
370 );
371 if (!EFI_ERROR (Status)) {
372 InsertTailList (&Task->Subtasks, &Subtask->Link);
373 } else {
374 FreePool (Subtask);
375 }
376 }
377 }
378 }
379 }
380
381 if (EFI_ERROR (Status)) {
382 Volume->DiskError = TRUE;
383 DEBUG ((DEBUG_ERROR, "FatDiskIo: error %r\n", Status));
384 }
385
386 return Status;
387}
388
394VOID
396 VOID
397 )
398{
399 EfiAcquireLock (&FatFsLock);
400}
401
414 VOID
415 )
416{
417 return EfiAcquireLockOrFail (&FatFsLock);
418}
419
425VOID
427 VOID
428 )
429{
430 EfiReleaseLock (&FatFsLock);
431}
432
440VOID
442 IN FAT_DIRENT *DirEnt
443 )
444{
445 if (DirEnt->FileString != NULL) {
446 FreePool (DirEnt->FileString);
447 }
448
449 FreePool (DirEnt);
450}
451
459VOID
461 IN FAT_VOLUME *Volume
462 )
463{
464 //
465 // Free disk cache
466 //
467 if (Volume->CacheBuffer != NULL) {
468 FreePool (Volume->CacheBuffer);
469 }
470
471 //
472 // Free directory cache
473 //
474 FatCleanupODirCache (Volume);
475 FreePool (Volume);
476}
477
486VOID
488 IN EFI_TIME *ETime,
489 OUT FAT_DATE_TIME *FTime
490 )
491{
492 //
493 // ignores timezone info in source ETime
494 //
495 if (ETime->Year > 1980) {
496 FTime->Date.Year = (UINT16)(ETime->Year - 1980);
497 }
498
499 if (ETime->Year >= 1980 + FAT_MAX_YEAR_FROM_1980) {
500 FTime->Date.Year = FAT_MAX_YEAR_FROM_1980;
501 }
502
503 FTime->Date.Month = ETime->Month;
504 FTime->Date.Day = ETime->Day;
505 FTime->Time.Hour = ETime->Hour;
506 FTime->Time.Minute = ETime->Minute;
507 FTime->Time.DoubleSecond = (UINT16)(ETime->Second / 2);
508}
509
518VOID
520 IN FAT_DATE_TIME *FTime,
521 OUT EFI_TIME *ETime
522 )
523{
524 ETime->Year = (UINT16)(FTime->Date.Year + 1980);
525 ETime->Month = (UINT8)FTime->Date.Month;
526 ETime->Day = (UINT8)FTime->Date.Day;
527 ETime->Hour = (UINT8)FTime->Time.Hour;
528 ETime->Minute = (UINT8)FTime->Time.Minute;
529 ETime->Second = (UINT8)(FTime->Time.DoubleSecond * 2);
530 ETime->Nanosecond = 0;
531 ETime->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
532 ETime->Daylight = 0;
533}
534
542VOID
544 OUT FAT_DATE_TIME *FatNow
545 )
546{
547 EFI_STATUS Status;
548 EFI_TIME Now;
549
550 Status = gRT->GetTime (&Now, NULL);
551 if (!EFI_ERROR (Status)) {
552 FatEfiTimeToFatTime (&Now, FatNow);
553 } else {
554 ZeroMem (&Now, sizeof (EFI_TIME));
555 Now.Year = 1980;
556 Now.Month = 1;
557 Now.Day = 1;
558 FatEfiTimeToFatTime (&Now, FatNow);
559 }
560}
561
572BOOLEAN
574 IN EFI_TIME *Time
575 )
576{
577 UINTN Day;
578 BOOLEAN ValidTime;
579
580 ValidTime = TRUE;
581
582 //
583 // Check the fields for range problems
584 // Fat can only support from 1980
585 //
586 if ((Time->Year < 1980) ||
587 (Time->Month < 1) ||
588 (Time->Month > 12) ||
589 (Time->Day < 1) ||
590 (Time->Day > 31) ||
591 (Time->Hour > 23) ||
592 (Time->Minute > 59) ||
593 (Time->Second > 59) ||
594 (Time->Nanosecond > 999999999)
595 )
596 {
597 ValidTime = FALSE;
598 } else {
599 //
600 // Perform a more specific check of the day of the month
601 //
602 Day = mMonthDays[Time->Month - 1];
603 if ((Time->Month == 2) && IS_LEAP_YEAR (Time->Year)) {
604 Day += 1;
605 //
606 // 1 extra day this month
607 //
608 }
609
610 if (Time->Day > Day) {
611 ValidTime = FALSE;
612 }
613 }
614
615 return ValidTime;
616}
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID FatCleanupODirCache(IN FAT_VOLUME *Volume)
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, IN FAT_TASK *Task)
Definition: DiskCache.c:493
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID FatFreeVolume(IN FAT_VOLUME *Volume)
Definition: Misc.c:460
VOID FatDestroyTask(FAT_TASK *Task)
Definition: Misc.c:51
VOID FatFatTimeToEfiTime(IN FAT_DATE_TIME *FTime, OUT EFI_TIME *ETime)
Definition: Misc.c:519
FAT_TASK * FatCreateTask(FAT_IFILE *IFile, EFI_FILE_IO_TOKEN *Token)
Definition: Misc.c:24
VOID FatEfiTimeToFatTime(IN EFI_TIME *ETime, OUT FAT_DATE_TIME *FTime)
Definition: Misc.c:487
EFI_STATUS FatQueueTask(IN FAT_IFILE *IFile, IN FAT_TASK *Task)
Definition: Misc.c:124
VOID FatGetCurrentFatTime(OUT FAT_DATE_TIME *FatNow)
Definition: Misc.c:543
EFI_STATUS FatAcquireLockOrFail(VOID)
Definition: Misc.c:413
LIST_ENTRY * FatDestroySubtask(FAT_SUBTASK *Subtask)
Definition: Misc.c:98
VOID EFIAPI FatOnAccessComplete(IN EFI_EVENT Event, IN VOID *Context)
Definition: Misc.c:252
VOID FatWaitNonblockingTask(FAT_IFILE *IFile)
Definition: Misc.c:75
BOOLEAN FatIsValidTime(IN EFI_TIME *Time)
Definition: Misc.c:573
EFI_STATUS FatDiskIo(IN FAT_VOLUME *Volume, IN IO_MODE IoMode, IN UINT64 Offset, IN UINTN BufferSize, IN OUT VOID *Buffer, IN FAT_TASK *Task)
Definition: Misc.c:315
EFI_STATUS FatAccessVolumeDirty(IN FAT_VOLUME *Volume, IN IO_MODE IoMode, IN VOID *DirtyValue)
Definition: Misc.c:230
VOID FatFreeDirEnt(IN FAT_DIRENT *DirEnt)
Definition: Misc.c:441
VOID FatAcquireLock(VOID)
Definition: Misc.c:395
VOID FatReleaseLock(VOID)
Definition: Misc.c:426
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
EFI_STATUS(EFIAPI * EFI_DISK_READ)(IN EFI_DISK_IO_PROTOCOL *This, IN UINT32 MediaId, IN UINT64 Offset, IN UINTN BufferSize, OUT VOID *Buffer)
Definition: DiskIo.h:52
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_TPL EFIAPI EfiGetCurrentTpl(VOID)
Definition: UefiLib.c:375
VOID EFIAPI EfiReleaseLock(IN EFI_LOCK *Lock)
Definition: UefiLib.c:499
EFI_STATUS EFIAPI EfiAcquireLockOrFail(IN EFI_LOCK *Lock)
Definition: UefiLib.c:463
VOID EFIAPI EfiAcquireLock(IN EFI_LOCK *Lock)
Definition: UefiLib.c:434
#define EFI_UNSPECIFIED_TIMEZONE
Definition: UefiSpec.h:58
Definition: Fat.h:217
Definition: Fat.h:227