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