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