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