]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsDir.c
450a707f183c8c6fd1b4d6436e1d5f812b87a5c7
[mirror_edk2.git] / ArmPlatformPkg / FileSystem / BootMonFs / BootMonFsDir.c
1 /** @file
2 *
3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
4 *
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
9 *
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.
12 *
13 **/
14
15 #include "BootMonFsInternal.h"
16
17 EFIAPI
18 EFI_STATUS
19 OpenBootMonFsOpenVolume (
20 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
21 OUT EFI_FILE_PROTOCOL **Root
22 )
23 {
24 BOOTMON_FS_INSTANCE *Instance;
25
26 Instance = BOOTMON_FS_FROM_FS_THIS (This);
27 if (Instance == NULL) {
28 return EFI_DEVICE_ERROR;
29 }
30
31 Instance->RootFile->Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
32
33 *Root = &Instance->RootFile->File;
34
35 return EFI_SUCCESS;
36 }
37
38 UINT32
39 BootMonFsGetImageLength (
40 IN BOOTMON_FS_FILE *File
41 )
42 {
43 UINT32 Index;
44 UINT32 FileSize;
45 LIST_ENTRY *RegionToFlushLink;
46 BOOTMON_FS_FILE_REGION *Region;
47
48 FileSize = 0;
49
50 // Look at all Flash areas to determine file size
51 for (Index = 0; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) {
52 FileSize += File->HwDescription.Region[Index].Size;
53 }
54
55 // Add the regions that have not been flushed yet
56 for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
57 !IsNull (&File->RegionToFlushLink, RegionToFlushLink);
58 RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink)
59 )
60 {
61 Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
62 if (Region->Offset + Region->Size > FileSize) {
63 FileSize += Region->Offset + Region->Size;
64 }
65 }
66
67 return FileSize;
68 }
69
70 UINTN
71 BootMonFsGetPhysicalSize (
72 IN BOOTMON_FS_FILE* File
73 )
74 {
75 // Return 0 for files that haven't yet been flushed to media
76 if (File->HwDescription.RegionCount == 0) {
77 return 0;
78 }
79
80 return ((File->HwDescription.BlockEnd - File->HwDescription.BlockStart) + 1 )
81 * File->Instance->Media->BlockSize;
82 }
83
84 EFIAPI
85 EFI_STATUS
86 BootMonFsSetDirPosition (
87 IN EFI_FILE_PROTOCOL *This,
88 IN UINT64 Position
89 )
90 {
91 BOOTMON_FS_FILE *File;
92
93 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
94 if (File == NULL) {
95 return EFI_INVALID_PARAMETER;
96 }
97
98 // UEFI Spec section 12.5:
99 // "The seek request for nonzero is not valid on open directories."
100 if (Position != 0) {
101 return EFI_UNSUPPORTED;
102 }
103 File->Position = Position;
104
105 return EFI_SUCCESS;
106 }
107
108 EFI_STATUS
109 BootMonFsOpenDirectory (
110 OUT EFI_FILE_PROTOCOL **NewHandle,
111 IN CHAR16 *FileName,
112 IN BOOTMON_FS_INSTANCE *Volume
113 )
114 {
115 ASSERT(0);
116
117 return EFI_UNSUPPORTED;
118 }
119
120 STATIC
121 EFI_STATUS
122 GetFileSystemVolumeLabelInfo (
123 IN BOOTMON_FS_INSTANCE *Instance,
124 IN OUT UINTN *BufferSize,
125 OUT VOID *Buffer
126 )
127 {
128 UINTN Size;
129 EFI_FILE_SYSTEM_VOLUME_LABEL *Label;
130 EFI_STATUS Status;
131
132 Label = Buffer;
133
134 // Value returned by StrSize includes null terminator.
135 Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL
136 + StrSize (Instance->FsInfo.VolumeLabel);
137
138 if (*BufferSize >= Size) {
139 CopyMem (&Label->VolumeLabel, &Instance->FsInfo.VolumeLabel, Size);
140 Status = EFI_SUCCESS;
141 } else {
142 Status = EFI_BUFFER_TOO_SMALL;
143 }
144 *BufferSize = Size;
145 return Status;
146 }
147
148 // Helper function that calculates a rough "free space" by:
149 // - Taking the media size
150 // - Subtracting the sum of all file sizes
151 // - Subtracting the block size times the number of files
152 // (To account for the blocks containing the HW_IMAGE_INFO
153 STATIC
154 UINT64
155 ComputeFreeSpace (
156 IN BOOTMON_FS_INSTANCE *Instance
157 )
158 {
159 LIST_ENTRY *FileLink;
160 UINT64 FileSizeSum;
161 UINT64 MediaSize;
162 UINTN NumFiles;
163 EFI_BLOCK_IO_MEDIA *Media;
164 BOOTMON_FS_FILE *File;
165
166 Media = Instance->BlockIo->Media;
167 MediaSize = Media->BlockSize * (Media->LastBlock + 1);
168
169 NumFiles = 0;
170 FileSizeSum = 0;
171 for (FileLink = GetFirstNode (&Instance->RootFile->Link);
172 !IsNull (&Instance->RootFile->Link, FileLink);
173 FileLink = GetNextNode (&Instance->RootFile->Link, FileLink)
174 )
175 {
176 File = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink);
177 FileSizeSum += BootMonFsGetImageLength (File);
178
179 NumFiles++;
180 }
181
182 return MediaSize - (FileSizeSum + (Media->BlockSize + NumFiles));
183 }
184
185 STATIC
186 EFI_STATUS
187 GetFilesystemInfo (
188 IN BOOTMON_FS_INSTANCE *Instance,
189 IN OUT UINTN *BufferSize,
190 OUT VOID *Buffer
191 )
192 {
193 EFI_STATUS Status;
194
195 if (*BufferSize >= Instance->FsInfo.Size) {
196 Instance->FsInfo.FreeSpace = ComputeFreeSpace (Instance);
197 CopyMem (Buffer, &Instance->FsInfo, Instance->FsInfo.Size);
198 Status = EFI_SUCCESS;
199 } else {
200 Status = EFI_BUFFER_TOO_SMALL;
201 }
202
203 *BufferSize = Instance->FsInfo.Size;
204 return Status;
205 }
206
207 STATIC
208 EFI_STATUS
209 GetFileInfo (
210 IN BOOTMON_FS_INSTANCE *Instance,
211 IN BOOTMON_FS_FILE *File,
212 IN OUT UINTN *BufferSize,
213 OUT VOID *Buffer
214 )
215 {
216 EFI_FILE_INFO *Info;
217 UINTN ResultSize;
218
219 ResultSize = SIZE_OF_EFI_FILE_INFO + StrSize (File->Info->FileName);
220
221 if (*BufferSize < ResultSize) {
222 *BufferSize = ResultSize;
223 return EFI_BUFFER_TOO_SMALL;
224 }
225
226 Info = Buffer;
227
228 CopyMem (Info, File->Info, ResultSize);
229 // Size of the information
230 Info->Size = ResultSize;
231
232 *BufferSize = ResultSize;
233
234 return EFI_SUCCESS;
235 }
236
237 STATIC
238 EFI_STATUS
239 GetBootMonFsFileInfo (
240 IN BOOTMON_FS_INSTANCE *Instance,
241 IN BOOTMON_FS_FILE *File,
242 IN OUT UINTN *BufferSize,
243 OUT VOID *Buffer
244 )
245 {
246 EFI_STATUS Status;
247 BOOTMON_FS_FILE_INFO *Info;
248 UINTN ResultSize;
249 UINTN Index;
250
251 if (File == Instance->RootFile) {
252 Status = EFI_UNSUPPORTED;
253 } else {
254 ResultSize = SIZE_OF_BOOTMON_FS_FILE_INFO;
255
256 if (*BufferSize < ResultSize) {
257 *BufferSize = ResultSize;
258 Status = EFI_BUFFER_TOO_SMALL;
259 } else {
260 Info = Buffer;
261
262 // Zero out the structure
263 ZeroMem (Info, ResultSize);
264
265 // Fill in the structure
266 Info->Size = ResultSize;
267
268 Info->EntryPoint = File->HwDescription.EntryPoint;
269 Info->RegionCount = File->HwDescription.RegionCount;
270 for (Index = 0; Index < File->HwDescription.RegionCount; Index++) {
271 Info->Region[Index].LoadAddress = File->HwDescription.Region[Index].LoadAddress;
272 Info->Region[Index].Size = File->HwDescription.Region[Index].Size;
273 Info->Region[Index].Offset = File->HwDescription.Region[Index].Offset;
274 Info->Region[Index].Checksum = File->HwDescription.Region[Index].Checksum;
275 }
276 *BufferSize = ResultSize;
277 Status = EFI_SUCCESS;
278 }
279 }
280
281 return Status;
282 }
283
284 /**
285 Set the name of a file.
286
287 This is a helper function for SetFileInfo().
288
289 @param[in] Instance A pointer to the description of the volume
290 the file belongs to.
291 @param[in] File A pointer to the description of the file.
292 @param[in] FileName A pointer to the new name of the file.
293
294 @retval EFI_SUCCESS The name was set.
295 @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
296 to a file that is already present.
297
298 **/
299 STATIC
300 EFI_STATUS
301 SetFileName (
302 IN BOOTMON_FS_INSTANCE *Instance,
303 IN BOOTMON_FS_FILE *File,
304 IN CONST CHAR16 *FileName
305 )
306 {
307 CHAR16 TruncFileName[MAX_NAME_LENGTH];
308 CHAR8 AsciiFileName[MAX_NAME_LENGTH];
309 BOOTMON_FS_FILE *SameFile;
310
311 // If the file path start with a \ strip it. The EFI Shell may
312 // insert a \ in front of the file name.
313 if (FileName[0] == L'\\') {
314 FileName++;
315 }
316
317 StrnCpy (TruncFileName, FileName, MAX_NAME_LENGTH - 1);
318 TruncFileName[MAX_NAME_LENGTH - 1] = 0;
319 UnicodeStrToAsciiStr (TruncFileName, AsciiFileName);
320
321 if (BootMonGetFileFromAsciiFileName (
322 File->Instance,
323 AsciiFileName,
324 &SameFile
325 ) != EFI_NOT_FOUND) {
326 // A file with that name already exists.
327 return EFI_ACCESS_DENIED;
328 } else {
329 // OK, change the filename.
330 AsciiStrToUnicodeStr (AsciiFileName, File->Info->FileName);
331 return EFI_SUCCESS;
332 }
333 }
334
335 /**
336 Set the size of a file.
337
338 This is a helper function for SetFileInfo().
339
340 @param[in] Instance A pointer to the description of the volume
341 the file belongs to.
342 @param[in] File A pointer to the description of the file.
343 @param[in] NewSize The requested new size for the file.
344
345 @retval EFI_SUCCESS The size was set.
346 @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed.
347
348 **/
349 STATIC
350 EFI_STATUS
351 SetFileSize (
352 IN BOOTMON_FS_INSTANCE *Instance,
353 IN BOOTMON_FS_FILE *BootMonFsFile,
354 IN UINTN NewSize
355 )
356 {
357 EFI_STATUS Status;
358 UINT32 OldSize;
359 LIST_ENTRY *RegionToFlushLink;
360 LIST_ENTRY *NextRegionToFlushLink;
361 BOOTMON_FS_FILE_REGION *Region;
362 EFI_FILE_PROTOCOL *File;
363 CHAR8 *Buffer;
364 UINTN BufferSize;
365 UINT64 StoredPosition;
366
367 OldSize = BootMonFsFile->Info->FileSize;
368
369 //
370 // In case of file truncation, force the regions waiting for writing to
371 // not overflow the new size of the file.
372 //
373 if (NewSize < OldSize) {
374 for (RegionToFlushLink = GetFirstNode (&BootMonFsFile->RegionToFlushLink);
375 !IsNull (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink);
376 )
377 {
378 NextRegionToFlushLink = GetNextNode (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink);
379 Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
380 if (Region->Offset > NewSize) {
381 RemoveEntryList (RegionToFlushLink);
382 FreePool (Region->Buffer);
383 FreePool (Region);
384 } else {
385 Region->Size = MIN (Region->Size, NewSize - Region->Offset);
386 }
387 RegionToFlushLink = NextRegionToFlushLink;
388 }
389
390 } else if (NewSize > OldSize) {
391 // Increasing a file's size is potentially complicated as it may require
392 // moving the image description on media. The simplest way to do it is to
393 // seek past the end of the file (which is valid in UEFI) and perform a
394 // Write.
395 File = &BootMonFsFile->File;
396
397 // Save position
398 Status = File->GetPosition (File, &StoredPosition);
399 if (EFI_ERROR (Status)) {
400 return Status;
401 }
402 // Set position at the end of the file
403 Status = File->SetPosition (File, OldSize);
404 if (EFI_ERROR (Status)) {
405 return Status;
406 }
407
408 BufferSize = NewSize - OldSize;
409 Buffer = AllocateZeroPool (BufferSize);
410 if (Buffer == NULL) {
411 return EFI_OUT_OF_RESOURCES;
412 }
413
414 Status = File->Write (File, &BufferSize, Buffer);
415 FreePool (Buffer);
416 if (EFI_ERROR (Status)) {
417 return Status;
418 }
419
420 // Restore saved position
421 Status = File->SetPosition (File, StoredPosition);
422 if (EFI_ERROR (Status)) {
423 return Status;
424 }
425 }
426
427 BootMonFsFile->Info->FileSize = NewSize;
428
429 return EFI_SUCCESS;
430 }
431
432 /**
433 Set information about a file.
434
435 @param[in] Instance A pointer to the description of the volume
436 the file belongs to.
437 @param[in] File A pointer to the description of the file.
438 @param[in] Info A pointer to the file information to write.
439
440 @retval EFI_SUCCESS The information was set.
441 @retval EFI_ACCESS_DENIED An attempt is being made to change the
442 EFI_FILE_DIRECTORY Attribute.
443 @retval EFI_ACCESS_DENIED The file was opened in read-only mode and an
444 attempt is being made to modify a field other
445 than Attribute.
446 @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
447 to a file that is already present.
448 @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only
449 attribute.
450 @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request
451 failed.
452
453 **/
454 STATIC
455 EFI_STATUS
456 SetFileInfo (
457 IN BOOTMON_FS_INSTANCE *Instance,
458 IN BOOTMON_FS_FILE *File,
459 IN EFI_FILE_INFO *Info
460 )
461 {
462 EFI_STATUS Status;
463 BOOLEAN FileSizeIsDifferent;
464 BOOLEAN FileNameIsDifferent;
465 BOOLEAN TimeIsDifferent;
466
467 //
468 // A directory can not be changed to a file and a file can
469 // not be changed to a directory.
470 //
471 if ((Info->Attribute & EFI_FILE_DIRECTORY) !=
472 (File->Info->Attribute & EFI_FILE_DIRECTORY) ) {
473 return EFI_ACCESS_DENIED;
474 }
475
476 FileSizeIsDifferent = (Info->FileSize != File->Info->FileSize);
477 FileNameIsDifferent = (StrnCmp (
478 Info->FileName,
479 File->Info->FileName,
480 MAX_NAME_LENGTH - 1
481 ) != 0);
482 //
483 // Check if the CreateTime, LastAccess or ModificationTime
484 // have been changed. The file system does not support file
485 // timestamps thus the three times in "File->Info" are
486 // always equal to zero. The following comparison actually
487 // checks if all three times are still equal to 0 or not.
488 //
489 TimeIsDifferent = CompareMem (
490 &Info->CreateTime,
491 &File->Info->CreateTime,
492 3 * sizeof (EFI_TIME)
493 ) != 0;
494
495 //
496 // For a file opened in read-only mode, only the Attribute field can be
497 // modified. The root directory open mode is forced to read-only at opening
498 // thus the following test protects the root directory to be somehow modified.
499 //
500 if (File->OpenMode == EFI_FILE_MODE_READ) {
501 if (FileSizeIsDifferent || FileNameIsDifferent || TimeIsDifferent) {
502 return EFI_ACCESS_DENIED;
503 }
504 }
505
506 if (TimeIsDifferent) {
507 return EFI_WRITE_PROTECTED;
508 }
509
510 if (FileSizeIsDifferent) {
511 Status = SetFileSize (Instance, File, Info->FileSize);
512 if (EFI_ERROR (Status)) {
513 return Status;
514 }
515 }
516
517 //
518 // Note down in RAM the Attribute field but we can not
519 // ask to store it in flash for the time being.
520 //
521 File->Info->Attribute = Info->Attribute;
522
523 if (FileNameIsDifferent) {
524 Status = SetFileName (Instance, File, Info->FileName);
525 if (EFI_ERROR (Status)) {
526 return Status;
527 }
528 }
529
530 return EFI_SUCCESS;
531 }
532
533 EFIAPI
534 EFI_STATUS
535 BootMonFsGetInfo (
536 IN EFI_FILE_PROTOCOL *This,
537 IN EFI_GUID *InformationType,
538 IN OUT UINTN *BufferSize,
539 OUT VOID *Buffer
540 )
541 {
542 EFI_STATUS Status;
543 BOOTMON_FS_FILE *File;
544 BOOTMON_FS_INSTANCE *Instance;
545
546 if ((This == NULL) ||
547 (InformationType == NULL) ||
548 (BufferSize == NULL) ||
549 ((Buffer == NULL) && (*BufferSize > 0)) ) {
550 return EFI_INVALID_PARAMETER;
551 }
552
553 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
554 if (File->Info == NULL) {
555 return EFI_INVALID_PARAMETER;
556 }
557 Instance = File->Instance;
558
559 // If the instance has not been initialized yet then do it ...
560 if (!Instance->Initialized) {
561 Status = BootMonFsInitialize (Instance);
562 } else {
563 Status = EFI_SUCCESS;
564 }
565
566 if (!EFI_ERROR (Status)) {
567 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)
568 != 0) {
569 Status = GetFileSystemVolumeLabelInfo (Instance, BufferSize, Buffer);
570 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {
571 Status = GetFilesystemInfo (Instance, BufferSize, Buffer);
572 } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {
573 Status = GetFileInfo (Instance, File, BufferSize, Buffer);
574 } else if (CompareGuid (InformationType, &gArmBootMonFsFileInfoGuid) != 0) {
575 Status = GetBootMonFsFileInfo (Instance, File, BufferSize, Buffer);
576 } else {
577 Status = EFI_UNSUPPORTED;
578 }
579 }
580
581 return Status;
582 }
583
584 /**
585 Set information about a file or a volume.
586
587 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
588 is the file handle the information is for.
589 @param[in] InformationType The type identifier for the information being set :
590 EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or
591 EFI_FILE_SYSTEM_VOLUME_LABEL_ID
592 @param[in] BufferSize The size, in bytes, of Buffer.
593 @param[in] Buffer A pointer to the data buffer to write. The type of the
594 data inside the buffer is indicated by InformationType.
595
596 @retval EFI_SUCCESS The information was set.
597 @retval EFI_UNSUPPORTED The InformationType is not known.
598 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.
599 @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
600 to a file that is already present.
601 @retval EFI_ACCESS_DENIED An attempt is being made to change the
602 EFI_FILE_DIRECTORY Attribute.
603 @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and
604 the file was opened in read-only mode and an
605 attempt is being made to modify a field other
606 than Attribute.
607 @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only
608 attribute.
609 @retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by
610 the data inside the buffer.
611 @retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed.
612 @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
613
614 **/
615 EFIAPI
616 EFI_STATUS
617 BootMonFsSetInfo (
618 IN EFI_FILE_PROTOCOL *This,
619 IN EFI_GUID *InformationType,
620 IN UINTN BufferSize,
621 IN VOID *Buffer
622 )
623 {
624 BOOTMON_FS_FILE *File;
625 EFI_FILE_INFO *Info;
626 EFI_FILE_SYSTEM_INFO *SystemInfo;
627
628 if ((This == NULL) ||
629 (InformationType == NULL) ||
630 (Buffer == NULL) ) {
631 return EFI_INVALID_PARAMETER;
632 }
633
634 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
635 if (File->Info == NULL) {
636 return EFI_INVALID_PARAMETER;
637 }
638
639 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
640 Info = Buffer;
641 if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) {
642 return EFI_INVALID_PARAMETER;
643 }
644 if (BufferSize < Info->Size) {
645 return EFI_BAD_BUFFER_SIZE;
646 }
647 return (SetFileInfo (File->Instance, File, Info));
648 }
649
650 //
651 // The only writable field in the other two information types
652 // (i.e. EFI_FILE_SYSTEM_INFO and EFI_FILE_SYSTEM_VOLUME_LABEL) is the
653 // filesystem volume label. This can be retrieved with GetInfo, but it is
654 // hard-coded into this driver, not stored on media.
655 //
656
657 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
658 SystemInfo = Buffer;
659 if (SystemInfo->Size <
660 (SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) {
661 return EFI_INVALID_PARAMETER;
662 }
663 if (BufferSize < SystemInfo->Size) {
664 return EFI_BAD_BUFFER_SIZE;
665 }
666 return EFI_WRITE_PROTECTED;
667 }
668
669 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
670 return EFI_WRITE_PROTECTED;
671 }
672
673 return EFI_UNSUPPORTED;
674 }
675
676 EFIAPI
677 EFI_STATUS
678 BootMonFsReadDirectory (
679 IN EFI_FILE_PROTOCOL *This,
680 IN OUT UINTN *BufferSize,
681 OUT VOID *Buffer
682 )
683 {
684 BOOTMON_FS_INSTANCE *Instance;
685 BOOTMON_FS_FILE *RootFile;
686 BOOTMON_FS_FILE *File;
687 EFI_FILE_INFO *Info;
688 UINTN NameSize;
689 UINTN ResultSize;
690 EFI_STATUS Status;
691 UINTN Index;
692
693 RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
694 if (RootFile == NULL) {
695 return EFI_INVALID_PARAMETER;
696 }
697
698 Instance = RootFile->Instance;
699 Status = BootMonGetFileFromPosition (Instance, RootFile->Position, &File);
700 if (EFI_ERROR (Status)) {
701 // No more file
702 *BufferSize = 0;
703 return EFI_SUCCESS;
704 }
705
706 NameSize = AsciiStrLen (File->HwDescription.Footer.Filename) + 1;
707 ResultSize = SIZE_OF_EFI_FILE_INFO + (NameSize * sizeof (CHAR16));
708 if (*BufferSize < ResultSize) {
709 *BufferSize = ResultSize;
710 return EFI_BUFFER_TOO_SMALL;
711 }
712
713 // Zero out the structure
714 Info = Buffer;
715 ZeroMem (Info, ResultSize);
716
717 // Fill in the structure
718 Info->Size = ResultSize;
719 Info->FileSize = BootMonFsGetImageLength (File);
720 Info->PhysicalSize = BootMonFsGetPhysicalSize (File);
721 for (Index = 0; Index < NameSize; Index++) {
722 Info->FileName[Index] = File->HwDescription.Footer.Filename[Index];
723 }
724
725 *BufferSize = ResultSize;
726 RootFile->Position++;
727
728 return EFI_SUCCESS;
729 }
730
731 EFIAPI
732 EFI_STATUS
733 BootMonFsFlushDirectory (
734 IN EFI_FILE_PROTOCOL *This
735 )
736 {
737 BOOTMON_FS_FILE *RootFile;
738 LIST_ENTRY *ListFiles;
739 LIST_ENTRY *Link;
740 BOOTMON_FS_FILE *File;
741
742 RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
743 if (RootFile == NULL) {
744 return EFI_INVALID_PARAMETER;
745 }
746
747 ListFiles = &RootFile->Link;
748
749 if (IsListEmpty (ListFiles)) {
750 return EFI_SUCCESS;
751 }
752
753 //
754 // Flush all the files that need to be flushed
755 //
756
757 // Go through all the list of files to flush them
758 for (Link = GetFirstNode (ListFiles);
759 !IsNull (ListFiles, Link);
760 Link = GetNextNode (ListFiles, Link)
761 )
762 {
763 File = BOOTMON_FS_FILE_FROM_LINK_THIS (Link);
764 File->File.Flush (&File->File);
765 }
766
767 return EFI_SUCCESS;
768 }