]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsDir.c
ArmPlatformPkg: remove ArmPlatformSysConfigLib library class
[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 CHAR8 AsciiFileName[MAX_NAME_LENGTH];\r
308 BOOTMON_FS_FILE *SameFile;\r
309\r
310 // If the file path start with a \ strip it. The EFI Shell may\r
311 // insert a \ in front of the file name.\r
312 if (FileName[0] == L'\\') {\r
313 FileName++;\r
94e0955d
OM
314 }\r
315\r
a5cd3bb0 316 UnicodeStrToAsciiStrS (FileName, AsciiFileName, MAX_NAME_LENGTH);\r
95204533
RC
317\r
318 if (BootMonGetFileFromAsciiFileName (\r
319 File->Instance,\r
320 AsciiFileName,\r
321 &SameFile\r
322 ) != EFI_NOT_FOUND) {\r
35d3b52d 323 // A file with that name already exists.\r
95204533 324 return EFI_ACCESS_DENIED;\r
94e0955d 325 } else {\r
35d3b52d 326 // OK, change the filename.\r
a5cd3bb0
AB
327 AsciiStrToUnicodeStrS (AsciiFileName, File->Info->FileName,\r
328 (File->Info->Size - SIZE_OF_EFI_FILE_INFO) / sizeof (CHAR16));\r
95204533 329 return EFI_SUCCESS;\r
94e0955d 330 }\r
94e0955d
OM
331}\r
332\r
95204533
RC
333/**\r
334 Set the size of a file.\r
335\r
336 This is a helper function for SetFileInfo().\r
337\r
338 @param[in] Instance A pointer to the description of the volume\r
339 the file belongs to.\r
340 @param[in] File A pointer to the description of the file.\r
341 @param[in] NewSize The requested new size for the file.\r
342\r
343 @retval EFI_SUCCESS The size was set.\r
344 @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed.\r
345\r
346**/\r
94e0955d
OM
347STATIC\r
348EFI_STATUS\r
349SetFileSize (\r
95204533
RC
350 IN BOOTMON_FS_INSTANCE *Instance,\r
351 IN BOOTMON_FS_FILE *BootMonFsFile,\r
352 IN UINTN NewSize\r
94e0955d
OM
353 )\r
354{\r
95204533
RC
355 EFI_STATUS Status;\r
356 UINT32 OldSize;\r
357 LIST_ENTRY *RegionToFlushLink;\r
358 LIST_ENTRY *NextRegionToFlushLink;\r
359 BOOTMON_FS_FILE_REGION *Region;\r
360 EFI_FILE_PROTOCOL *File;\r
361 CHAR8 *Buffer;\r
362 UINTN BufferSize;\r
363 UINT64 StoredPosition;\r
94e0955d 364\r
95204533 365 OldSize = BootMonFsFile->Info->FileSize;\r
94e0955d 366\r
95204533
RC
367 //\r
368 // In case of file truncation, force the regions waiting for writing to\r
369 // not overflow the new size of the file.\r
370 //\r
371 if (NewSize < OldSize) {\r
372 for (RegionToFlushLink = GetFirstNode (&BootMonFsFile->RegionToFlushLink);\r
373 !IsNull (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink);\r
374 )\r
375 {\r
376 NextRegionToFlushLink = GetNextNode (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink);\r
377 Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;\r
378 if (Region->Offset > NewSize) {\r
379 RemoveEntryList (RegionToFlushLink);\r
380 FreePool (Region->Buffer);\r
381 FreePool (Region);\r
382 } else {\r
383 Region->Size = MIN (Region->Size, NewSize - Region->Offset);\r
384 }\r
385 RegionToFlushLink = NextRegionToFlushLink;\r
386 }\r
94e0955d 387\r
95204533 388 } else if (NewSize > OldSize) {\r
94e0955d
OM
389 // Increasing a file's size is potentially complicated as it may require\r
390 // moving the image description on media. The simplest way to do it is to\r
391 // seek past the end of the file (which is valid in UEFI) and perform a\r
392 // Write.\r
95204533 393 File = &BootMonFsFile->File;\r
94e0955d
OM
394\r
395 // Save position\r
396 Status = File->GetPosition (File, &StoredPosition);\r
397 if (EFI_ERROR (Status)) {\r
398 return Status;\r
399 }\r
95204533
RC
400 // Set position at the end of the file\r
401 Status = File->SetPosition (File, OldSize);\r
94e0955d
OM
402 if (EFI_ERROR (Status)) {\r
403 return Status;\r
404 }\r
95204533
RC
405\r
406 BufferSize = NewSize - OldSize;\r
407 Buffer = AllocateZeroPool (BufferSize);\r
408 if (Buffer == NULL) {\r
409 return EFI_OUT_OF_RESOURCES;\r
94e0955d
OM
410 }\r
411\r
95204533
RC
412 Status = File->Write (File, &BufferSize, Buffer);\r
413 FreePool (Buffer);\r
94e0955d
OM
414 if (EFI_ERROR (Status)) {\r
415 return Status;\r
416 }\r
417\r
95204533
RC
418 // Restore saved position\r
419 Status = File->SetPosition (File, StoredPosition);\r
94e0955d
OM
420 if (EFI_ERROR (Status)) {\r
421 return Status;\r
422 }\r
423 }\r
95204533
RC
424\r
425 BootMonFsFile->Info->FileSize = NewSize;\r
426\r
94e0955d
OM
427 return EFI_SUCCESS;\r
428}\r
429\r
95204533
RC
430/**\r
431 Set information about a file.\r
432\r
433 @param[in] Instance A pointer to the description of the volume\r
434 the file belongs to.\r
435 @param[in] File A pointer to the description of the file.\r
436 @param[in] Info A pointer to the file information to write.\r
437\r
438 @retval EFI_SUCCESS The information was set.\r
439 @retval EFI_ACCESS_DENIED An attempt is being made to change the\r
440 EFI_FILE_DIRECTORY Attribute.\r
441 @retval EFI_ACCESS_DENIED The file was opened in read-only mode and an\r
442 attempt is being made to modify a field other\r
443 than Attribute.\r
444 @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file\r
445 to a file that is already present.\r
446 @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only\r
447 attribute.\r
448 @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request\r
449 failed.\r
450\r
451**/\r
452STATIC\r
94e0955d
OM
453EFI_STATUS\r
454SetFileInfo (\r
95204533
RC
455 IN BOOTMON_FS_INSTANCE *Instance,\r
456 IN BOOTMON_FS_FILE *File,\r
457 IN EFI_FILE_INFO *Info\r
94e0955d
OM
458 )\r
459{\r
95204533
RC
460 EFI_STATUS Status;\r
461 BOOLEAN FileSizeIsDifferent;\r
462 BOOLEAN FileNameIsDifferent;\r
463 BOOLEAN TimeIsDifferent;\r
94e0955d 464\r
95204533
RC
465 //\r
466 // A directory can not be changed to a file and a file can\r
467 // not be changed to a directory.\r
468 //\r
469 if ((Info->Attribute & EFI_FILE_DIRECTORY) !=\r
470 (File->Info->Attribute & EFI_FILE_DIRECTORY) ) {\r
471 return EFI_ACCESS_DENIED;\r
472 }\r
94e0955d 473\r
95204533
RC
474 FileSizeIsDifferent = (Info->FileSize != File->Info->FileSize);\r
475 FileNameIsDifferent = (StrnCmp (\r
476 Info->FileName,\r
477 File->Info->FileName,\r
478 MAX_NAME_LENGTH - 1\r
479 ) != 0);\r
480 //\r
481 // Check if the CreateTime, LastAccess or ModificationTime\r
482 // have been changed. The file system does not support file\r
483 // timestamps thus the three times in "File->Info" are\r
484 // always equal to zero. The following comparison actually\r
485 // checks if all three times are still equal to 0 or not.\r
486 //\r
487 TimeIsDifferent = CompareMem (\r
488 &Info->CreateTime,\r
489 &File->Info->CreateTime,\r
490 3 * sizeof (EFI_TIME)\r
491 ) != 0;\r
94e0955d 492\r
95204533
RC
493 //\r
494 // For a file opened in read-only mode, only the Attribute field can be\r
495 // modified. The root directory open mode is forced to read-only at opening\r
496 // thus the following test protects the root directory to be somehow modified.\r
497 //\r
498 if (File->OpenMode == EFI_FILE_MODE_READ) {\r
499 if (FileSizeIsDifferent || FileNameIsDifferent || TimeIsDifferent) {\r
94e0955d
OM
500 return EFI_ACCESS_DENIED;\r
501 }\r
95204533
RC
502 }\r
503\r
504 if (TimeIsDifferent) {\r
505 return EFI_WRITE_PROTECTED;\r
506 }\r
94e0955d 507\r
95204533
RC
508 if (FileSizeIsDifferent) {\r
509 Status = SetFileSize (Instance, File, Info->FileSize);\r
94e0955d
OM
510 if (EFI_ERROR (Status)) {\r
511 return Status;\r
512 }\r
95204533 513 }\r
94e0955d 514\r
95204533
RC
515 //\r
516 // Note down in RAM the Attribute field but we can not\r
517 // ask to store it in flash for the time being.\r
518 //\r
519 File->Info->Attribute = Info->Attribute;\r
520\r
521 if (FileNameIsDifferent) {\r
522 Status = SetFileName (Instance, File, Info->FileName);\r
94e0955d
OM
523 if (EFI_ERROR (Status)) {\r
524 return Status;\r
525 }\r
94e0955d 526 }\r
95204533
RC
527\r
528 return EFI_SUCCESS;\r
94e0955d
OM
529}\r
530\r
531EFIAPI\r
532EFI_STATUS\r
533BootMonFsGetInfo (\r
534 IN EFI_FILE_PROTOCOL *This,\r
535 IN EFI_GUID *InformationType,\r
536 IN OUT UINTN *BufferSize,\r
537 OUT VOID *Buffer\r
538 )\r
539{\r
540 EFI_STATUS Status;\r
541 BOOTMON_FS_FILE *File;\r
542 BOOTMON_FS_INSTANCE *Instance;\r
543\r
95204533
RC
544 if ((This == NULL) ||\r
545 (InformationType == NULL) ||\r
546 (BufferSize == NULL) ||\r
547 ((Buffer == NULL) && (*BufferSize > 0)) ) {\r
548 return EFI_INVALID_PARAMETER;\r
94e0955d
OM
549 }\r
550\r
95204533
RC
551 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);\r
552 if (File->Info == NULL) {\r
553 return EFI_INVALID_PARAMETER;\r
554 }\r
94e0955d
OM
555 Instance = File->Instance;\r
556\r
557 // If the instance has not been initialized yet then do it ...\r
558 if (!Instance->Initialized) {\r
559 Status = BootMonFsInitialize (Instance);\r
560 } else {\r
561 Status = EFI_SUCCESS;\r
562 }\r
563\r
564 if (!EFI_ERROR (Status)) {\r
565 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)\r
566 != 0) {\r
567 Status = GetFileSystemVolumeLabelInfo (Instance, BufferSize, Buffer);\r
568 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) {\r
569 Status = GetFilesystemInfo (Instance, BufferSize, Buffer);\r
570 } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) {\r
571 Status = GetFileInfo (Instance, File, BufferSize, Buffer);\r
da5daf36
HL
572 } else if (CompareGuid (InformationType, &gArmBootMonFsFileInfoGuid) != 0) {\r
573 Status = GetBootMonFsFileInfo (Instance, File, BufferSize, Buffer);\r
94e0955d
OM
574 } else {\r
575 Status = EFI_UNSUPPORTED;\r
576 }\r
577 }\r
578\r
579 return Status;\r
580}\r
581\r
95204533
RC
582/**\r
583 Set information about a file or a volume.\r
584\r
585 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
586 is the file handle the information is for.\r
587 @param[in] InformationType The type identifier for the information being set :\r
588 EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or\r
589 EFI_FILE_SYSTEM_VOLUME_LABEL_ID\r
590 @param[in] BufferSize The size, in bytes, of Buffer.\r
591 @param[in] Buffer A pointer to the data buffer to write. The type of the\r
592 data inside the buffer is indicated by InformationType.\r
593\r
594 @retval EFI_SUCCESS The information was set.\r
595 @retval EFI_UNSUPPORTED The InformationType is not known.\r
596 @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.\r
597 @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file\r
598 to a file that is already present.\r
599 @retval EFI_ACCESS_DENIED An attempt is being made to change the\r
600 EFI_FILE_DIRECTORY Attribute.\r
601 @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and\r
602 the file was opened in read-only mode and an\r
603 attempt is being made to modify a field other\r
604 than Attribute.\r
605 @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only\r
606 attribute.\r
607 @retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by\r
608 the data inside the buffer.\r
609 @retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed.\r
610 @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.\r
611\r
612**/\r
94e0955d
OM
613EFIAPI\r
614EFI_STATUS\r
615BootMonFsSetInfo (\r
616 IN EFI_FILE_PROTOCOL *This,\r
617 IN EFI_GUID *InformationType,\r
618 IN UINTN BufferSize,\r
619 IN VOID *Buffer\r
620 )\r
621{\r
95204533
RC
622 BOOTMON_FS_FILE *File;\r
623 EFI_FILE_INFO *Info;\r
624 EFI_FILE_SYSTEM_INFO *SystemInfo;\r
625\r
626 if ((This == NULL) ||\r
627 (InformationType == NULL) ||\r
628 (Buffer == NULL) ) {\r
629 return EFI_INVALID_PARAMETER;\r
630 }\r
94e0955d
OM
631\r
632 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);\r
95204533
RC
633 if (File->Info == NULL) {\r
634 return EFI_INVALID_PARAMETER;\r
94e0955d
OM
635 }\r
636\r
95204533
RC
637 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
638 Info = Buffer;\r
639 if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) {\r
640 return EFI_INVALID_PARAMETER;\r
641 }\r
642 if (BufferSize < Info->Size) {\r
643 return EFI_BAD_BUFFER_SIZE;\r
644 }\r
645 return (SetFileInfo (File->Instance, File, Info));\r
646 }\r
94e0955d 647\r
95204533
RC
648 //\r
649 // The only writable field in the other two information types\r
650 // (i.e. EFI_FILE_SYSTEM_INFO and EFI_FILE_SYSTEM_VOLUME_LABEL) is the\r
651 // filesystem volume label. This can be retrieved with GetInfo, but it is\r
652 // hard-coded into this driver, not stored on media.\r
653 //\r
654\r
655 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
656 SystemInfo = Buffer;\r
657 if (SystemInfo->Size <\r
658 (SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) {\r
659 return EFI_INVALID_PARAMETER;\r
660 }\r
661 if (BufferSize < SystemInfo->Size) {\r
662 return EFI_BAD_BUFFER_SIZE;\r
663 }\r
664 return EFI_WRITE_PROTECTED;\r
94e0955d
OM
665 }\r
666\r
95204533
RC
667 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
668 return EFI_WRITE_PROTECTED;\r
669 }\r
670\r
671 return EFI_UNSUPPORTED;\r
94e0955d
OM
672}\r
673\r
674EFIAPI\r
675EFI_STATUS\r
676BootMonFsReadDirectory (\r
677 IN EFI_FILE_PROTOCOL *This,\r
678 IN OUT UINTN *BufferSize,\r
679 OUT VOID *Buffer\r
680 )\r
681{\r
682 BOOTMON_FS_INSTANCE *Instance;\r
683 BOOTMON_FS_FILE *RootFile;\r
684 BOOTMON_FS_FILE *File;\r
685 EFI_FILE_INFO *Info;\r
686 UINTN NameSize;\r
687 UINTN ResultSize;\r
688 EFI_STATUS Status;\r
689 UINTN Index;\r
690\r
691 RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This);\r
692 if (RootFile == NULL) {\r
693 return EFI_INVALID_PARAMETER;\r
694 }\r
695\r
696 Instance = RootFile->Instance;\r
697 Status = BootMonGetFileFromPosition (Instance, RootFile->Position, &File);\r
698 if (EFI_ERROR (Status)) {\r
699 // No more file\r
700 *BufferSize = 0;\r
701 return EFI_SUCCESS;\r
702 }\r
703\r
704 NameSize = AsciiStrLen (File->HwDescription.Footer.Filename) + 1;\r
705 ResultSize = SIZE_OF_EFI_FILE_INFO + (NameSize * sizeof (CHAR16));\r
706 if (*BufferSize < ResultSize) {\r
707 *BufferSize = ResultSize;\r
708 return EFI_BUFFER_TOO_SMALL;\r
709 }\r
710\r
711 // Zero out the structure\r
712 Info = Buffer;\r
713 ZeroMem (Info, ResultSize);\r
714\r
715 // Fill in the structure\r
716 Info->Size = ResultSize;\r
717 Info->FileSize = BootMonFsGetImageLength (File);\r
718 Info->PhysicalSize = BootMonFsGetPhysicalSize (File);\r
719 for (Index = 0; Index < NameSize; Index++) {\r
720 Info->FileName[Index] = File->HwDescription.Footer.Filename[Index];\r
721 }\r
722\r
723 *BufferSize = ResultSize;\r
724 RootFile->Position++;\r
725\r
726 return EFI_SUCCESS;\r
727}\r
728\r
729EFIAPI\r
730EFI_STATUS\r
731BootMonFsFlushDirectory (\r
732 IN EFI_FILE_PROTOCOL *This\r
733 )\r
734{\r
735 BOOTMON_FS_FILE *RootFile;\r
736 LIST_ENTRY *ListFiles;\r
737 LIST_ENTRY *Link;\r
738 BOOTMON_FS_FILE *File;\r
739\r
740 RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This);\r
741 if (RootFile == NULL) {\r
742 return EFI_INVALID_PARAMETER;\r
743 }\r
744\r
745 ListFiles = &RootFile->Link;\r
746\r
747 if (IsListEmpty (ListFiles)) {\r
748 return EFI_SUCCESS;\r
749 }\r
750\r
751 //\r
752 // Flush all the files that need to be flushed\r
753 //\r
754\r
755 // Go through all the list of files to flush them\r
756 for (Link = GetFirstNode (ListFiles);\r
757 !IsNull (ListFiles, Link);\r
758 Link = GetNextNode (ListFiles, Link)\r
759 )\r
760 {\r
761 File = BOOTMON_FS_FILE_FROM_LINK_THIS (Link);\r
762 File->File.Flush (&File->File);\r
763 }\r
764\r
765 return EFI_SUCCESS;\r
766}\r