]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsEntryPoint.c
ArmPlatformPkg/BootMonFs: Fix the setting of information about a file
[mirror_edk2.git] / ArmPlatformPkg / FileSystem / BootMonFs / BootMonFsEntryPoint.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 <Library/BaseMemoryLib.h>\r
16#include <Library/DevicePathLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
18#include <Library/PrintLib.h>\r
19#include <Library/UefiBootServicesTableLib.h>\r
20\r
21#include <Protocol/DevicePathFromText.h>\r
22#include <Protocol/DriverBinding.h>\r
23\r
24#include "BootMonFsInternal.h"\r
25\r
26EFI_DEVICE_PATH* mBootMonFsSupportedDevicePaths;\r
94e0955d
OM
27LIST_ENTRY mInstances;\r
28\r
29EFI_FILE_PROTOCOL mBootMonFsRootTemplate = {\r
30 EFI_FILE_PROTOCOL_REVISION,\r
31 BootMonFsOpenFile,\r
32 BootMonFsCloseFile,\r
33 BootMonFsDeleteFail,\r
34 BootMonFsReadDirectory,\r
35 BootMonFsWriteFile,\r
36 BootMonFsGetPositionUnsupported, // UEFI Spec: GetPosition not valid on dirs\r
37 BootMonFsSetDirPosition,\r
38 BootMonFsGetInfo,\r
39 BootMonFsSetInfo,\r
40 BootMonFsFlushDirectory\r
41};\r
42\r
43EFI_FILE_PROTOCOL mBootMonFsFileTemplate = {\r
44 EFI_FILE_PROTOCOL_REVISION,\r
45 BootMonFsOpenFile,\r
46 BootMonFsCloseFile,\r
47 BootMonFsDelete,\r
48 BootMonFsReadFile,\r
49 BootMonFsWriteFile,\r
50 BootMonFsGetPosition,\r
51 BootMonFsSetPosition,\r
52 BootMonFsGetInfo,\r
53 BootMonFsSetInfo,\r
54 BootMonFsFlushFile\r
55};\r
56\r
95204533
RC
57/**\r
58 Search for a file given its name coded in Ascii.\r
59\r
60 When searching through the files of the volume, if a file is currently not\r
61 open, its name was written on the media and is kept in RAM in the\r
62 "HwDescription.Footer.Filename[]" field of the file's description.\r
63\r
64 If a file is currently open, its name might not have been written on the\r
65 media yet, and as the "HwDescription" is a mirror in RAM of what is on the\r
66 media the "HwDescription.Footer.Filename[]" might be outdated. In that case,\r
67 the up to date name of the file is stored in the "Info" field of the file's\r
68 description.\r
69\r
70 @param[in] Instance Pointer to the description of the volume in which\r
71 the file has to be search for.\r
72 @param[in] AsciiFileName Name of the file.\r
73\r
74 @param[out] File Pointer to the description of the file if the\r
75 file was found.\r
76\r
77 @retval EFI_SUCCESS The file was found.\r
78 @retval EFI_NOT_FOUND The file was not found.\r
79\r
80**/\r
94e0955d
OM
81EFI_STATUS\r
82BootMonGetFileFromAsciiFileName (\r
83 IN BOOTMON_FS_INSTANCE *Instance,\r
84 IN CHAR8* AsciiFileName,\r
85 OUT BOOTMON_FS_FILE **File\r
86 )\r
87{\r
95204533
RC
88 LIST_ENTRY *Entry;\r
89 BOOTMON_FS_FILE *FileEntry;\r
90 CHAR8 OpenFileAsciiFileName[MAX_NAME_LENGTH];\r
91 CHAR8 *AsciiFileNameToCompare;\r
94e0955d
OM
92\r
93 // Go through all the files in the list and return the file handle\r
94 for (Entry = GetFirstNode (&Instance->RootFile->Link);\r
95204533
RC
95 !IsNull (&Instance->RootFile->Link, Entry);\r
96 Entry = GetNextNode (&Instance->RootFile->Link, Entry)\r
97 )\r
94e0955d
OM
98 {\r
99 FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry);\r
95204533
RC
100 if (FileEntry->Info != NULL) {\r
101 UnicodeStrToAsciiStr (FileEntry->Info->FileName, OpenFileAsciiFileName);\r
102 AsciiFileNameToCompare = OpenFileAsciiFileName;\r
103 } else {\r
104 AsciiFileNameToCompare = FileEntry->HwDescription.Footer.Filename;\r
105 }\r
106\r
107 if (AsciiStrCmp (AsciiFileNameToCompare, AsciiFileName) == 0) {\r
94e0955d
OM
108 *File = FileEntry;\r
109 return EFI_SUCCESS;\r
110 }\r
111 }\r
112 return EFI_NOT_FOUND;\r
113}\r
114\r
115EFI_STATUS\r
116BootMonGetFileFromPosition (\r
117 IN BOOTMON_FS_INSTANCE *Instance,\r
118 IN UINTN Position,\r
119 OUT BOOTMON_FS_FILE **File\r
120 )\r
121{\r
122 LIST_ENTRY *Entry;\r
123 BOOTMON_FS_FILE *FileEntry;\r
124\r
125 // Go through all the files in the list and return the file handle\r
126 for (Entry = GetFirstNode (&Instance->RootFile->Link);\r
127 !IsNull (&Instance->RootFile->Link, Entry) && (&Instance->RootFile->Link != Entry);\r
128 Entry = GetNextNode (&Instance->RootFile->Link, Entry)\r
129 )\r
130 {\r
131 if (Position == 0) {\r
132 FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry);\r
133 *File = FileEntry;\r
134 return EFI_SUCCESS;\r
135 }\r
136 Position--;\r
137 }\r
138 return EFI_NOT_FOUND;\r
139}\r
140\r
141EFI_STATUS\r
142BootMonFsCreateFile (\r
143 IN BOOTMON_FS_INSTANCE *Instance,\r
144 OUT BOOTMON_FS_FILE **File\r
145 )\r
146{\r
147 BOOTMON_FS_FILE *NewFile;\r
148\r
149 NewFile = (BOOTMON_FS_FILE*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE));\r
150 if (NewFile == NULL) {\r
151 return EFI_OUT_OF_RESOURCES;\r
152 }\r
153\r
154 NewFile->Signature = BOOTMON_FS_FILE_SIGNATURE;\r
155 InitializeListHead (&NewFile->Link);\r
156 InitializeListHead (&NewFile->RegionToFlushLink);\r
157 NewFile->Instance = Instance;\r
158\r
159 // If the created file is the root file then create a directory EFI_FILE_PROTOCOL\r
160 if (Instance->RootFile == *File) {\r
161 CopyMem (&NewFile->File, &mBootMonFsRootTemplate, sizeof (mBootMonFsRootTemplate));\r
162 } else {\r
163 CopyMem (&NewFile->File, &mBootMonFsFileTemplate, sizeof (mBootMonFsFileTemplate));\r
164 }\r
165 *File = NewFile;\r
166 return EFI_SUCCESS;\r
167}\r
168\r
169STATIC\r
170EFI_STATUS\r
171SupportedDevicePathsInit (\r
172 VOID\r
173 )\r
174{\r
175 EFI_STATUS Status;\r
176 CHAR16* DevicePathListStr;\r
177 CHAR16* DevicePathStr;\r
178 CHAR16* NextDevicePathStr;\r
179 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;\r
180 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
181\r
182 Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);\r
183 ASSERT_EFI_ERROR (Status);\r
184\r
185 // Initialize Variable\r
186 DevicePathListStr = (CHAR16*)PcdGetPtr (PcdBootMonFsSupportedDevicePaths);\r
187 mBootMonFsSupportedDevicePaths = NULL;\r
188\r
189 // Extract the Device Path instances from the multi-device path string\r
190 while ((DevicePathListStr != NULL) && (DevicePathListStr[0] != L'\0')) {\r
191 NextDevicePathStr = StrStr (DevicePathListStr, L";");\r
192 if (NextDevicePathStr == NULL) {\r
193 DevicePathStr = DevicePathListStr;\r
194 DevicePathListStr = NULL;\r
195 } else {\r
196 DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DevicePathListStr + 1) * sizeof (CHAR16), DevicePathListStr);\r
197 if (DevicePathStr == NULL) {\r
198 return EFI_OUT_OF_RESOURCES;\r
199 }\r
200 *(DevicePathStr + (NextDevicePathStr - DevicePathListStr)) = L'\0';\r
201 DevicePathListStr = NextDevicePathStr;\r
202 if (DevicePathListStr[0] == L';') {\r
203 DevicePathListStr++;\r
204 }\r
205 }\r
206\r
207 Instance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr);\r
208 ASSERT (Instance != NULL);\r
209 mBootMonFsSupportedDevicePaths = AppendDevicePathInstance (mBootMonFsSupportedDevicePaths, Instance);\r
210\r
211 if (NextDevicePathStr != NULL) {\r
212 FreePool (DevicePathStr);\r
213 }\r
214 FreePool (Instance);\r
215 }\r
216\r
217 if (mBootMonFsSupportedDevicePaths == NULL) {\r
218 return EFI_UNSUPPORTED;\r
219 } else {\r
220 return EFI_SUCCESS;\r
221 }\r
222}\r
223\r
224EFI_STATUS\r
225EFIAPI\r
226BootMonFsDriverSupported (\r
227 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,\r
228 IN EFI_HANDLE ControllerHandle,\r
229 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL\r
230 )\r
231{\r
232 EFI_DISK_IO_PROTOCOL *DiskIo;\r
233 EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol;\r
234 EFI_DEVICE_PATH_PROTOCOL *SupportedDevicePath;\r
235 EFI_DEVICE_PATH_PROTOCOL *SupportedDevicePaths;\r
236 EFI_STATUS Status;\r
237 UINTN Size1;\r
238 UINTN Size2;\r
239\r
240 //\r
241 // Open the IO Abstraction(s) needed to perform the supported test\r
242 //\r
243 Status = gBS->OpenProtocol (\r
244 ControllerHandle,\r
245 &gEfiDiskIoProtocolGuid,\r
246 (VOID **) &DiskIo,\r
c3b6d975 247 gImageHandle,\r
94e0955d
OM
248 ControllerHandle,\r
249 EFI_OPEN_PROTOCOL_BY_DRIVER\r
250 );\r
251\r
252 if (EFI_ERROR (Status)) {\r
253 return Status;\r
254 }\r
255 //\r
256 // Close the I/O Abstraction(s) used to perform the supported test\r
257 //\r
258 gBS->CloseProtocol (\r
259 ControllerHandle,\r
260 &gEfiDiskIoProtocolGuid,\r
c3b6d975 261 gImageHandle,\r
94e0955d
OM
262 ControllerHandle\r
263 );\r
264\r
265 // Check that BlockIo protocol instance exists\r
266 Status = gBS->OpenProtocol (\r
267 ControllerHandle,\r
268 &gEfiBlockIoProtocolGuid,\r
269 NULL,\r
c3b6d975 270 gImageHandle,\r
94e0955d
OM
271 ControllerHandle,\r
272 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
273 );\r
274 if (EFI_ERROR (Status)) {\r
275 return Status;\r
276 }\r
277\r
278 // Check if a DevicePath is attached to the handle\r
279 Status = gBS->OpenProtocol (\r
280 ControllerHandle,\r
281 &gEfiDevicePathProtocolGuid,\r
282 (VOID **)&DevicePathProtocol,\r
c3b6d975 283 gImageHandle,\r
94e0955d
OM
284 ControllerHandle,\r
285 EFI_OPEN_PROTOCOL_BY_DRIVER\r
286 );\r
287 if (EFI_ERROR (Status)) {\r
288 return Status;\r
289 }\r
290\r
291 // Check if the Device Path is the one which contains the Boot Monitor File System\r
292 Size1 = GetDevicePathSize (DevicePathProtocol);\r
293\r
294 // Go through the list of Device Path Instances\r
295 Status = EFI_UNSUPPORTED;\r
296 SupportedDevicePaths = mBootMonFsSupportedDevicePaths;\r
297 while (SupportedDevicePaths != NULL) {\r
298 SupportedDevicePath = GetNextDevicePathInstance (&SupportedDevicePaths, &Size2);\r
299\r
300 if ((Size1 == Size2) && (CompareMem (DevicePathProtocol, SupportedDevicePath, Size1) == 0)) {\r
301 // The Device Path is supported\r
302 Status = EFI_SUCCESS;\r
303 break;\r
304 }\r
305 }\r
306\r
c3b6d975 307 gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, gImageHandle, ControllerHandle);\r
94e0955d
OM
308 return Status;\r
309}\r
310\r
311EFI_STATUS\r
312EFIAPI\r
313BootMonFsDriverStart (\r
314 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,\r
315 IN EFI_HANDLE ControllerHandle,\r
316 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL\r
317 )\r
318{\r
319 BOOTMON_FS_INSTANCE *Instance;\r
320 EFI_STATUS Status;\r
321 UINTN VolumeNameSize;\r
95204533 322 EFI_FILE_INFO *Info;\r
94e0955d
OM
323\r
324 Instance = AllocateZeroPool (sizeof (BOOTMON_FS_INSTANCE));\r
325 if (Instance == NULL) {\r
326 return EFI_OUT_OF_RESOURCES;\r
327 }\r
328\r
329 // Initialize the BlockIo of the Instance\r
330 Status = gBS->OpenProtocol (\r
331 ControllerHandle,\r
332 &gEfiBlockIoProtocolGuid,\r
333 (VOID **)&(Instance->BlockIo),\r
c3b6d975 334 gImageHandle,\r
94e0955d
OM
335 ControllerHandle,\r
336 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
337 );\r
338 if (EFI_ERROR (Status)) {\r
95204533 339 goto Error;\r
94e0955d
OM
340 }\r
341\r
342 Status = gBS->OpenProtocol (\r
343 ControllerHandle,\r
344 &gEfiDiskIoProtocolGuid,\r
345 (VOID **)&(Instance->DiskIo),\r
c3b6d975 346 gImageHandle,\r
94e0955d
OM
347 ControllerHandle,\r
348 EFI_OPEN_PROTOCOL_BY_DRIVER\r
349 );\r
350 if (EFI_ERROR (Status)) {\r
95204533 351 goto Error;\r
94e0955d
OM
352 }\r
353\r
354 //\r
355 // Initialize the attributes of the Instance\r
356 //\r
357 Instance->Signature = BOOTMON_FS_SIGNATURE;\r
358 Instance->ControllerHandle = ControllerHandle;\r
359 Instance->Media = Instance->BlockIo->Media;\r
360 Instance->Binding = DriverBinding;\r
361\r
362 // Initialize the Simple File System Protocol\r
363 Instance->Fs.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;\r
364 Instance->Fs.OpenVolume = OpenBootMonFsOpenVolume;\r
365\r
366 // Volume name + L' ' + '2' digit number\r
367 VolumeNameSize = StrSize (BOOTMON_FS_VOLUME_LABEL) + (3 * sizeof (CHAR16));\r
368\r
369 // Initialize FileSystem Information\r
370 Instance->FsInfo.Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + VolumeNameSize;\r
371 Instance->FsInfo.BlockSize = Instance->Media->BlockSize;\r
372 Instance->FsInfo.ReadOnly = FALSE;\r
373 Instance->FsInfo.VolumeSize =\r
374 Instance->Media->BlockSize * (Instance->Media->LastBlock - Instance->Media->LowestAlignedLba);\r
375 CopyMem (Instance->FsInfo.VolumeLabel, BOOTMON_FS_VOLUME_LABEL, StrSize (BOOTMON_FS_VOLUME_LABEL));\r
376\r
377 // Initialize the root file\r
378 Status = BootMonFsCreateFile (Instance, &Instance->RootFile);\r
379 if (EFI_ERROR (Status)) {\r
95204533 380 goto Error;\r
94e0955d
OM
381 }\r
382\r
95204533
RC
383 Info = AllocateZeroPool (sizeof (EFI_FILE_INFO));\r
384 if (Info == NULL) {\r
385 Status = EFI_OUT_OF_RESOURCES;\r
386 goto Error;\r
387 }\r
388 Instance->RootFile->Info = Info;\r
389\r
94e0955d
OM
390 // Initialize the DevicePath of the Instance\r
391 Status = gBS->OpenProtocol (\r
392 ControllerHandle,\r
393 &gEfiDevicePathProtocolGuid,\r
394 (VOID **)&(Instance->DevicePath),\r
c3b6d975 395 gImageHandle,\r
94e0955d
OM
396 ControllerHandle,\r
397 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
398 );\r
399 if (EFI_ERROR (Status)) {\r
95204533 400 goto Error;\r
94e0955d
OM
401 }\r
402\r
403 //\r
404 // Install the Simple File System Protocol\r
405 //\r
406 Status = gBS->InstallMultipleProtocolInterfaces (\r
407 &ControllerHandle,\r
408 &gEfiSimpleFileSystemProtocolGuid, &Instance->Fs,\r
409 NULL\r
410 );\r
95204533
RC
411 if (EFI_ERROR (Status)) {\r
412 goto Error;\r
413 }\r
94e0955d
OM
414\r
415 InsertTailList (&mInstances, &Instance->Link);\r
416\r
95204533
RC
417 return EFI_SUCCESS;\r
418\r
419Error:\r
420\r
421 if (Instance->RootFile != NULL) {\r
422 if (Instance->RootFile->Info != NULL) {\r
423 FreePool (Instance->RootFile->Info);\r
424 }\r
425 FreePool (Instance->RootFile);\r
426 }\r
427 FreePool (Instance);\r
428\r
94e0955d
OM
429 return Status;\r
430}\r
431\r
432\r
433EFI_STATUS\r
434EFIAPI\r
435BootMonFsDriverStop (\r
436 IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,\r
437 IN EFI_HANDLE ControllerHandle,\r
438 IN UINTN NumberOfChildren,\r
439 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
440 )\r
441{\r
442 BOOTMON_FS_INSTANCE *Instance;\r
443 LIST_ENTRY *Link;\r
444 EFI_STATUS Status;\r
445 BOOLEAN InstanceFound;\r
446\r
447 // Find instance from ControllerHandle.\r
448 Instance = NULL;\r
449 InstanceFound = FALSE;\r
450 // For each instance in mInstances:\r
451 for (Link = GetFirstNode (&mInstances); !IsNull (&mInstances, Link); Link = GetNextNode (&mInstances, Link)) {\r
452 Instance = BOOTMON_FS_FROM_LINK (Link);\r
453\r
454 if (Instance->ControllerHandle == ControllerHandle) {\r
455 InstanceFound = TRUE;\r
456 break;\r
457 }\r
458 }\r
459 ASSERT (InstanceFound == TRUE);\r
460\r
461 gBS->CloseProtocol (\r
462 ControllerHandle,\r
463 &gEfiDevicePathProtocolGuid,\r
464 DriverBinding->ImageHandle,\r
465 ControllerHandle);\r
466\r
467 gBS->CloseProtocol (\r
468 ControllerHandle,\r
469 &gEfiDiskIoProtocolGuid,\r
470 DriverBinding->ImageHandle,\r
471 ControllerHandle);\r
472\r
473 gBS->CloseProtocol (\r
474 ControllerHandle,\r
475 &gEfiBlockIoProtocolGuid,\r
476 DriverBinding->ImageHandle,\r
477 ControllerHandle);\r
478\r
479 Status = gBS->UninstallMultipleProtocolInterfaces (\r
480 &ControllerHandle,\r
481 &gEfiSimpleFileSystemProtocolGuid, &Instance->Fs,\r
482 NULL);\r
95204533
RC
483\r
484 FreePool (Instance->RootFile->Info);\r
485 FreePool (Instance->RootFile);\r
486 FreePool (Instance);\r
94e0955d
OM
487\r
488 return Status;\r
489}\r
490\r
491//\r
492// Simple Network Protocol Driver Global Variables\r
493//\r
494EFI_DRIVER_BINDING_PROTOCOL mBootMonFsDriverBinding = {\r
495 BootMonFsDriverSupported,\r
496 BootMonFsDriverStart,\r
497 BootMonFsDriverStop,\r
498 0xa,\r
499 NULL,\r
500 NULL\r
501};\r
502\r
503EFI_STATUS\r
504EFIAPI\r
505BootMonFsEntryPoint (\r
506 IN EFI_HANDLE ImageHandle,\r
507 IN EFI_SYSTEM_TABLE *SystemTable\r
508 )\r
509{\r
510 EFI_STATUS Status;\r
511\r
94e0955d
OM
512 InitializeListHead (&mInstances);\r
513\r
514 // Initialize the list of Device Paths that could support BootMonFs\r
515 Status = SupportedDevicePathsInit ();\r
516 if (!EFI_ERROR (Status)) {\r
517 Status = gBS->InstallMultipleProtocolInterfaces (\r
518 &ImageHandle,\r
519 &gEfiDriverBindingProtocolGuid, &mBootMonFsDriverBinding,\r
520 NULL\r
521 );\r
522 ASSERT_EFI_ERROR (Status);\r
523 } else {\r
524 DEBUG((EFI_D_ERROR,"Warning: No Device Paths supporting BootMonFs have been defined in the PCD.\n"));\r
525 }\r
526\r
527 return Status;\r
528}\r