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